Santhosh has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/295898

Change subject: WIP: Use TemplateData to find template params in target language
......................................................................

WIP: Use TemplateData to find template params in target language

This will allow us to adapt templates if target template has same
name for source param names or alias to that.
Also we adapt tempaltes without nameless parameters like {{foo|bar}}

We are using templatedata api in target wikis for this.

Change-Id: I6f71dee7d3c05964f8dfa5e49bd8a839036a6064
TODO: more testiong, unit tests
---
M modules/tools/ext.cx.tools.template.js
M tests/qunit/tools/ext.cx.tools.template.test.js
2 files changed, 120 insertions(+), 51 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation 
refs/changes/98/295898/1

diff --git a/modules/tools/ext.cx.tools.template.js 
b/modules/tools/ext.cx.tools.template.js
index 5388d82..d4a6240 100644
--- a/modules/tools/ext.cx.tools.template.js
+++ b/modules/tools/ext.cx.tools.template.js
@@ -11,7 +11,8 @@
        'use strict';
 
        var targetTemplateNamespace = {},
-               cachedTemplateRequests = {};
+               cachedTemplateRequests = {},
+               cachedTemplateDataAPIRequests = {};
 
        /**
         * TemplateTool encapsulates the handling of templates in translation.
@@ -22,11 +23,15 @@
         *
         * @class
         */
-       function TemplateTool( element ) {
+       function TemplateTool( element, options ) {
                this.$template = $( element );
                this.templateData = null;
                this.templateTitle = null;
                this.templateMapping = null;
+               this.options = $.extend( {}, mw.cx.TemplateTool.defaults, 
options );
+               this.siteMapper = this.options.siteMapper;
+               this.sourceLanguage = this.options.sourceLanguage;
+               this.targetLanguage = this.options.targetLanguage;
        }
 
        /**
@@ -41,7 +46,7 @@
         * Get the template data from source section. Target section
         * might not have it always.
         */
-       TemplateTool.prototype.getTemplateData = function () {
+       TemplateTool.prototype.getSourceTemplateData = function () {
                var templateData,
                        aboutAttr = this.$template.attr( 'about' );
 
@@ -64,19 +69,48 @@
        };
 
        /**
+        * [getTargetTemplateData description]
+        * @return {[type]} [description]
+        */
+       TemplateTool.prototype.getTargetTemplateData = function () {
+               var self = this;
+
+               if ( cachedTemplateDataAPIRequests[ this.templateTitle ] ) {
+                       return cachedTemplateDataAPIRequests[ 
this.templateTitle ];
+               }
+
+               cachedTemplateDataAPIRequests[ this.templateTitle ] =
+                       this.siteMapper.getApi( self.targetLanguage ).get( {
+                               action: 'templatedata',
+                               titles: 'Template:' + this.templateTitle,
+                               redirects: true,
+                               format: 'json'
+                       }, {
+                               dataType: 'jsonp',
+                               // This prevents warnings about the 
unrecognized parameter "_"
+                               cache: true
+                       } ).then( function ( response ) {
+                               var pageId = Object.keys( response.pages )[ 0 ];
+                               return response.pages[ pageId ] || {};
+                       } );
+
+               return cachedTemplateDataAPIRequests[ this.templateTitle ];
+       };
+
+       /**
         * Get the namespace translation in a wiki.
         * Uses the canonical name for lookup.
         *
         * @param {string} language
         * @return {jQuery.Promise}
         */
-       function getTemplateNamespaceTranslation( language ) {
+       TemplateTool.prototype.getTemplateNamespaceTranslation = function ( 
language ) {
                if ( targetTemplateNamespace[ language ] ) {
                        return $.Deferred().resolve( targetTemplateNamespace[ 
language ] ).promise();
                }
 
                // TODO: Refactor to avoid global reference
-               return mw.cx.siteMapper.getApi( language ).get( {
+               return this.siteMapper.getApi( language ).get( {
                        action: 'query',
                        meta: 'siteinfo',
                        siprop: 'namespaces',
@@ -96,29 +130,39 @@
                                }
                        }
                } );
-       }
+       };
 
        /**
         * Get the template mapping if any set by source.filter module
         */
        TemplateTool.prototype.getTemplateMapping = function () {
-               return this.$template.data( 'template-mapping' );
+               var self = this;
+               return this.getTargetTemplateData().then( function ( 
templateData ) {
+                       templateData.cxMapping = self.$template.data( 
'template-mapping' ) || {};
+                       return templateData;
+               } );
        };
 
        /**
         * Adapt a template using template mapping
         */
        TemplateTool.prototype.adapt = function () {
+               var targetParams;
                mw.log( '[CX] Adapting template ' + this.templateTitle + ' 
based on mapping.' );
                // Update the name of the template
-               this.templateData.parts[ 0 ].template.target.wt = 
this.templateMapping.targetname;
-               this.templateData.parts[ 0 ].template.params = 
this.getTargetParams( this.getSourceParams() );
+               this.adaptTitle( this.templateMapping.cxMapping.targetname || 
this.templateMapping.title );
+               targetParams = this.getTargetParams( this.getSourceParams() );
+               if ( $.isEmptyObject( targetParams ) ) {
+                       return false;
+               }
+               this.templateData.parts[ 0 ].template.params = targetParams;
                this.$template.attr( 'data-mw', JSON.stringify( 
this.templateData ) );
 
                // Make templates uneditable unless whitelisted
                if ( !this.templateMapping.editable ) {
                        this.$template.data( 'editable', false );
                }
+               return true;
        };
 
        /**
@@ -141,21 +185,33 @@
 
                // Update the template parameters
                $.each( sourceParams, function ( key, value ) {
-                       // Drop empty parameters
-                       // TODO: Shouldn't we only do this if the parameter is 
named?
-                       // I can imagine {{Foo||baz}} breaks badly if we remove 
the one from middle.
-                       if ( $.trim( value ) === '' ) {
+                       if ( !isNaN( key ) ) {
+                               // Key is like "1" or "2" etc. Unnamed params.
+                               targetParams[ key ] = value;
                                return;
                        }
 
-                       // Copy over other parameters, but map known keys
-                       if ( self.templateMapping.parameters &&
-                               self.templateMapping.parameters[ key ] !== 
undefined
-                       ) {
-                               key = self.templateMapping.parameters[ key ];
+                       if ( self.templateMapping.cxMapping.parameters &&
+                               self.templateMapping.cxMapping.parameters[ key 
] ) {
+                               targetParams[ 
self.templateMapping.cxMapping.parameters[ key ] ] = value;
+                               return;
                        }
 
-                       targetParams[ key ] = value;
+                       if ( !self.templateMapping.params ) {
+                               return;
+                       }
+                       // Copy over other parameters, but map known keys
+                       if ( self.templateMapping.params &&
+                               self.templateMapping.params[ key ] ) {
+                               targetParams[ key ] = value;
+                               return;
+                       }
+                       $.each( self.templateMapping.params, function ( 
paramName, param ) {
+                               var aliases = param.aliases;
+                               if ( aliases.indexOf( key ) >= 0 ) {
+                                       targetParams[ paramName ] = value;
+                               }
+                       } );
                } );
 
                return targetParams;
@@ -167,7 +223,7 @@
        TemplateTool.prototype.adaptTitle = function ( targetTitle ) {
                var self = this;
                // Update the name of the template. We need template name 
without namespace
-               getTemplateNamespaceTranslation( mw.cx.targetLanguage )
+               this.getTemplateNamespaceTranslation( this.targetLanguage )
                        .done( function ( translatedNamespace ) {
                                var templateName;
 
@@ -203,8 +259,7 @@
        TemplateTool.prototype.process = function () {
                var self = this;
 
-               this.templateData = this.getTemplateData();
-               this.templateMapping = this.getTemplateMapping();
+               this.templateData = this.getSourceTemplateData();
 
                if ( !this.templateData || ( this.templateData.parts && 
this.templateData.parts.length > 1 ) ) {
                        // Either the template is missing mw data or having 
multiple parts.
@@ -216,15 +271,15 @@
                }
 
                this.templateTitle = this.templateData.parts[ 0 
].template.target.wt;
-
-               return this.getTargetTemplate()
-                       .then( function ( targetTitle ) {
+               return this.getTemplateMapping()
+                       .then( function ( targetTemplateData ) {
+                               var adaptResult = false;
+                               self.templateMapping = targetTemplateData;
                                self.markReadOnly();
-                               if ( self.templateMapping ) {
-                                       self.adapt();
-                               } else if ( targetTitle ) {
-                                       self.adaptTitle( targetTitle );
-                               } else {
+                               if ( targetTemplateData ) {
+                                       adaptResult = self.adapt();
+                               }
+                               if ( !adaptResult ) {
                                        self.deconstruct();
                                }
                        } )
@@ -249,14 +304,14 @@
                }
 
                // TODO: Avoid direct access to globals
-               api = mw.cx.siteMapper.getApi( mw.cx.sourceLanguage );
+               api = this.siteMapper.getApi( this.sourceLanguage );
 
                // Note that we use canonical namespace 'Template' for title.
                request = api.get( {
                        action: 'query',
                        titles: 'Template:' + this.templateTitle,
                        prop: 'langlinks',
-                       lllang: mw.cx.siteMapper.getWikiDomainCode( 
mw.cx.targetLanguage ),
+                       lllang: this.siteMapper.getWikiDomainCode( 
this.targetLanguage ),
                        redirects: true,
                        format: 'json'
                }, {
@@ -277,6 +332,13 @@
                return request;
        };
 
+       mw.cx.TemplateTool = TemplateTool;
+       mw.cx.TemplateTool.defaults = {
+               siteMapper: mw.cx.siteMapper,
+               sourceLanguage: mw.cx.sourceLanguage,
+               targetLanguage: mw.cx.targetLanguage
+       };
+
        /**
         * Processes each template in given section.
         *
@@ -285,22 +347,17 @@
        function processTemplates( $section ) {
                var i, template, templates = [];
 
-               if ( $section.is( '[typeof*="mw:Transclusion"]' ) ) {
+               if ( $section.is( '[typeof~="mw:Transclusion"]' ) ) {
                        templates.push( $section );
                }
                templates = templates.concat(
                        // Convert the internal templates to a js array
-                       $.makeArray( $section.find( 
'[typeof*="mw:Transclusion"]' ) )
+                       $.makeArray( $section.find( 
'[typeof~="mw:Transclusion"]' ) )
                );
                for ( i = 0; i < templates.length; i++ ) {
-                       template = new TemplateTool( templates[ i ] );
+                       template = new mw.cx.TemplateTool( templates[ i ] );
                        template.process();
                }
-       }
-
-       if ( typeof QUnit !== undefined ) {
-               // Expose this module for unit testing
-               mw.cx.TemplateTool = TemplateTool;
        }
 
        $( function () {
diff --git a/tests/qunit/tools/ext.cx.tools.template.test.js 
b/tests/qunit/tools/ext.cx.tools.template.test.js
index a53f4ea..d99277e 100644
--- a/tests/qunit/tools/ext.cx.tools.template.test.js
+++ b/tests/qunit/tools/ext.cx.tools.template.test.js
@@ -28,14 +28,16 @@
                $fixture.load( testDataPath + 'template-lang-ml.html', function 
() {
                        var templateTool, $templates = $fixture.find( 
'[typeof="mw:Transclusion"]' );
 
-                       mw.cx.targetLanguage = 'ml';
-                       mw.cx.sourceLanguage = 'en';
                        // Tesing lang-ml template. It exist in en and ml. So 
will be passed through
                        // But it will be readonly.
                        $.each( $templates, function ( index, template ) {
                                var $template = $( template );
 
-                               templateTool = new mw.cx.TemplateTool( 
$template );
+                               templateTool = new mw.cx.TemplateTool( 
$template, {
+                                       siteMapper: mw.cx.siteMapper,
+                                       sourceLanguage: 'ml',
+                                       targetLanguage: 'en'
+                               } );
                                templateTool.process().then( function () {
                                        assert.assertTrue( $template.is( 
'[contenteditable=false]' ), 'Template is readonly' );
                                        QUnit.start();
@@ -52,15 +54,19 @@
                $fixture.load( testDataPath + 'template-lang-ml.html', function 
() {
                        var templateTool, $templates = $fixture.find( 
'[typeof="mw:Transclusion"]' );
 
-                       mw.cx.targetLanguage = 'ca';
-                       mw.cx.sourceLanguage = 'en';
                        $.each( $templates, function ( index, template ) {
                                // Tesing lang-ml template. It exist in en but 
not in ca. So will be deconstructed
                                var $template = $( template );
 
-                               templateTool = new mw.cx.TemplateTool( 
$template );
+                               templateTool = new mw.cx.TemplateTool( 
$template, {
+                                       siteMapper: mw.cx.siteMapper,
+                                       sourceLanguage: 'ca',
+                                       targetLanguage: 'en'
+                               } );
                                templateTool.process().then( function () {
-                                       assert.assertFalse( $template.is( 
'[typeof="mw:Transclusion"]' ), 'Template is deconstructed' );
+                                       assert.assertTrue(
+                                               $template.is( 
'[typeof="mw:Transclusion"]' ),
+                                               'Template is mapped using 
TemplateData extension data' );
                                        QUnit.start();
                                } );
                        } );
@@ -81,7 +87,11 @@
                                // Tesing Ficha_de_taxón. As per template 
mapping for es-ca, it should be renamed to Taxocaixa
                                var $template = $( template );
 
-                               templateTool = new mw.cx.TemplateTool( 
$template );
+                               templateTool = new mw.cx.TemplateTool( 
$template, {
+                                       siteMapper: mw.cx.siteMapper,
+                                       sourceLanguage: mw.cx.sourceLanguage,
+                                       targetLanguage: mw.cx.targetLanguage
+                               } );
                                templateTool.process().then( function () {
                                        var templateData = $template.data( 'mw' 
);
                                        assert.assertTrue( $template.is( 
'[contenteditable=false]' ), 'Template is readonly' );
@@ -100,14 +110,16 @@
                $fixture.load( testDataPath + 'template-cita-noticia-es.html', 
function () {
                        var templateTool, $templates = $fixture.find( 
'[typeof="mw:Transclusion"]' );
 
-                       mw.cx.sourceLanguage = 'es';
-                       mw.cx.targetLanguage = 'ca';
                        $.each( $templates, function ( index, template ) {
                                // Tesing Cita Noticia. As per template mapping 
for es-ca, it should be renamed to Ref-notícia
                                var $template = $( template ),
                                        originalTemplateParams = Object.keys( 
$template.data( 'mw' ).parts[ 0 ].template.params );
 
-                               templateTool = new mw.cx.TemplateTool( 
$template );
+                               templateTool = new mw.cx.TemplateTool( 
$template, {
+                                       siteMapper: mw.cx.siteMapper,
+                                       sourceLanguage: 'es',
+                                       targetLanguage: 'ca'
+                               } );
                                templateTool.process().then( function () {
                                        var i, key, mappedKey,
                                                templateData = $template.data( 
'mw' ),

-- 
To view, visit https://gerrit.wikimedia.org/r/295898
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6f71dee7d3c05964f8dfa5e49bd8a839036a6064
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/ContentTranslation
Gerrit-Branch: master
Gerrit-Owner: Santhosh <santhosh.thottin...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to