https://www.mediawiki.org/wiki/Special:Code/MediaWiki/113577

Revision: 113577
Author:   nikerabbit
Date:     2012-03-11 18:17:27 +0000 (Sun, 11 Mar 2012)
Log Message:
-----------
* Support for shared TTMServer databases was added (only when using $wgConf)
* Output of TTMServer api module has changed
* TTMServer configs can override the link symbol by adding value for symbol in 
the config
* Added some simple tests

Modified Paths:
--------------
    trunk/extensions/Translate/README
    trunk/extensions/Translate/Translate.i18n.php
    trunk/extensions/Translate/Translate.php
    trunk/extensions/Translate/api/ApiTTMServer.php
    trunk/extensions/Translate/scripts/ttmserver-export.php
    trunk/extensions/Translate/utils/TTMServer.php
    trunk/extensions/Translate/utils/TranslationHelpers.php

Added Paths:
-----------
    trunk/extensions/Translate/tests/TTMServerTest.php

Modified: trunk/extensions/Translate/README
===================================================================
--- trunk/extensions/Translate/README   2012-03-11 17:26:07 UTC (rev 113576)
+++ trunk/extensions/Translate/README   2012-03-11 18:17:27 UTC (rev 113577)
@@ -30,6 +30,11 @@
  https://translatewiki.net/docs/Translate/html/
 
 == Change log ==
+* 2012-03-11
+- Support for shared TTMServer databases was added
+- Suggestions from different TTMServers are now grouped
+- Output of TTMServer api module has changed
+- TTMServer configs can override the link symbol by adding value for symbol in 
the config
 * 2012-03-07
 - $wgTranslateGroupStructure is no longer used. If you are using aggregate 
message
   groups, you can remove the old settings and everything still works as 
expected.

Modified: trunk/extensions/Translate/Translate.i18n.php
===================================================================
--- trunk/extensions/Translate/Translate.i18n.php       2012-03-11 17:26:07 UTC 
(rev 113576)
+++ trunk/extensions/Translate/Translate.i18n.php       2012-03-11 18:17:27 UTC 
(rev 113577)
@@ -83,6 +83,7 @@
        'translate-edit-committed'          => 'Current translation in 
software',
        'translate-edit-warnings'           => 'Warnings about incomplete 
translations',
        'translate-edit-tmsugs'             => 'Suggestions from translation 
memories and machine translation',
+       'translate-edit-tmmatch-source'     => 'Translation source text: $1',
        'translate-edit-tmmatch'            => '$1% match',
        'translate-use-suggestion'          => 'Replace current translation 
with this suggestion.',
 

Modified: trunk/extensions/Translate/Translate.php
===================================================================
--- trunk/extensions/Translate/Translate.php    2012-03-11 17:26:07 UTC (rev 
113576)
+++ trunk/extensions/Translate/Translate.php    2012-03-11 18:17:27 UTC (rev 
113577)
@@ -345,8 +345,6 @@
 $wgTranslateTranslationServices['TTMServer'] = array(
        'database' => false, // Passed to wfGetDB
        'cutoff' => 0.75,
-       'timeout-sync' => 0, // Unused
-       'timeout-async' => 0, // Unused
        'type' => 'ttmserver',
        'public' => false,
 );

Modified: trunk/extensions/Translate/api/ApiTTMServer.php
===================================================================
--- trunk/extensions/Translate/api/ApiTTMServer.php     2012-03-11 17:26:07 UTC 
(rev 113576)
+++ trunk/extensions/Translate/api/ApiTTMServer.php     2012-03-11 18:17:27 UTC 
(rev 113577)
@@ -29,8 +29,8 @@
 
                $result = $this->getResult();
                foreach ( $suggestions as $sug ) {
-                       $result->setContent( $sug, $sug['target'] );
-                       unset( $sug['target'] );
+                       $sug['location'] = $server->expandLocation( $sug );
+                       unset( $sug['wiki'] );
                        $result->addValue( $this->getModuleName(), null, $sug );
                }
 

Modified: trunk/extensions/Translate/scripts/ttmserver-export.php
===================================================================
--- trunk/extensions/Translate/scripts/ttmserver-export.php     2012-03-11 
17:26:07 UTC (rev 113576)
+++ trunk/extensions/Translate/scripts/ttmserver-export.php     2012-03-11 
18:17:27 UTC (rev 113577)
@@ -22,10 +22,14 @@
  * @since 2012-01-26
  */
 class TTMServerBootstrap extends Maintenance {
+       /// @var Array Configuration of requested TTMServer
+       protected $config;
+
        public function __construct() {
                parent::__construct();
                $this->mDescription = 'Script to bootstrap TTMServer';
                $this->addOption( 'threads', 'Number of threads', 
/*required*/false, /*has arg*/true );
+               $this->addOption( 'server', 'Server configuration identifier', 
/*required*/false, /*has arg*/true );
                $this->setBatchSize( 100 );
                $this->start = microtime( true );
        }
@@ -38,23 +42,55 @@
        }
 
        public function execute() {
-               $server = TTMServer::primary();
-               if ( $server instanceof FakeTTMServer ) {
+               global $wgTranslateTranslationServices;
+
+               // TTMServer is the id of the enabled-by-default instance
+               $configKey = $this->getOption( 'server', 'TTMServer' );
+               if ( isset( $wgTranslateTranslationServices[$configKey] ) ) {
+                       $this->config = $config = 
$wgTranslateTranslationServices[$configKey];
+                       $server = new TTMServer( $config );
+               } else {
                        $this->error( "Translation memory is not configured 
properly", 1 );
                }
 
                $dbw = $server->getDB( DB_MASTER );
 
-               $this->statusLine( 'Deleting sources.. ', 1 );
-               $dbw->delete( 'translate_tms', '*', __METHOD__ );
-               $this->output( 'translations.. ', 1 );
-               $dbw->delete( 'translate_tmt', '*', __METHOD__ );
-               $this->output( 'fulltext.. ', 1 );
-               $dbw->delete( 'translate_tmf', '*', __METHOD__ );
-               $table = $dbw->tableName( 'translate_tmf' );
-               $dbw->query( "DROP INDEX tmf_text ON $table" );
-               $this->output( 'done!', 1 );
+               if ( $server->isShared() ) {
+                       $wiki = array( 'tms_wiki' => wfWikiId() );
 
+                       $this->statusLine( 'Deleting fulltext.. ', 1 );
+                       $dbw->deleteJoin(
+                               'translate_tmf', 'translate_tms',
+                               'tmf_sid', 'tms_sid',
+                               $wiki, __METHOD__
+                       );
+
+                       $this->output( 'translations.. ', 1 );
+                       $dbw->deleteJoin(
+                               'translate_tmt', 'translate_tms',
+                               'tmt_sid', 'tms_sid',
+                               $wiki, __METHOD__
+                       );
+
+                       $this->output( 'sources.. ', 1 );
+                       $dbw->delete( 'translate_tms', $wiki, __METHOD__ );
+                       $this->output( 'done!', 1 );
+               } else {
+                       // For dedicated databases we can just wipe out 
everything,
+                       // drop the index during bootstrap and readd it later.
+                       $this->statusLine( 'Deleting sources.. ', 1 );
+                       $dbw->delete( 'translate_tms', '*', __METHOD__ );
+                       $this->output( 'translations.. ', 1 );
+                       $dbw->delete( 'translate_tmt', '*', __METHOD__ );
+                       $this->output( 'fulltext.. ', 1 );
+                       $dbw->delete( 'translate_tmf', '*', __METHOD__ );
+                       $table = $dbw->tableName( 'translate_tmf' );
+                       $dbw->ignoreErrors( true );
+                       $dbw->query( "DROP INDEX tmf_text ON $table" );
+                       $dbw->ignoreErrors( false );
+                       $this->output( 'done!', 1 );
+               }
+
                $this->statusLine( 'Loading groups... ', 2 );
                $groups = MessageGroups::singleton()->getGroups();
                $this->output( 'done!', 2 );
@@ -99,17 +135,19 @@
                        pcntl_waitpid( $pid, $status );
                }
 
-               $this->statusLine( 'Adding fulltext index...', 9 );
-               $table = $dbw->tableName( 'translate_tmf' );
-               $dbw->query( "CREATE FULLTEXT INDEX tmf_text ON $table 
(tmf_text)" );
-               $this->output( ' done!', 9 );
+               if ( !$server->isShared() ) {
+                       $this->statusLine( 'Adding fulltext index...', 9 );
+                       $table = $dbw->tableName( 'translate_tmf' );
+                       $dbw->query( "CREATE FULLTEXT INDEX tmf_text ON $table 
(tmf_text)" );
+                       $this->output( ' done!', 9 );
+               }
        }
 
        protected function exportGroup( MessageGroup $group, $multi = false ) {
                // Make sure all existing connections are dead,
                // we can't use them in forked children.
                LBFactory::destroyInstance();
-               $server = TTMServer::primary();
+               $server = new TTMServer( $this->config );
 
                $id = $group->getId();
                $sourceLanguage = $group->getSourceLanguage();

Added: trunk/extensions/Translate/tests/TTMServerTest.php
===================================================================
--- trunk/extensions/Translate/tests/TTMServerTest.php                          
(rev 0)
+++ trunk/extensions/Translate/tests/TTMServerTest.php  2012-03-11 18:17:27 UTC 
(rev 113577)
@@ -0,0 +1,115 @@
+<?php
+/**
+ * Tests for TTMServer
+ *
+ * @file
+ * @author Niklas Laxström
+ * @copyright Copyright © 2012, Niklas Laxström
+ * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 
2.0 or later
+ */
+
+class TTMServerTest extends MediaWikiTestCase {
+
+       protected $config;
+
+       protected function setUp() {
+               global $wgTranslateTranslationServices;
+               $this->config = $wgTranslateTranslationServices;
+               parent::setUp();
+
+               $wgTranslateTranslationServices = array();
+               $wgTranslateTranslationServices['localtm'] = array(
+                       'url' => 'http://example.com/sandwiki/api.php',
+                       'displayname' => 'example.com',
+                       'cutoff' => 0.75,
+                       'type' => 'ttmserver',
+               );
+
+               $wgTranslateTranslationServices['apitm'] = array(
+                       'url' => 'http://example.com/w/api.php',
+                       'displayname' => 'example.com',
+                       'cutoff' => 0.75,
+                       'timeout-sync' => 4,
+                       'timeout-async' => 4,
+                       'type' => 'remote-ttmserver',
+               );
+
+               $wgTranslateTranslationServices['sharedtm'] = array(
+                       'database' => 'sharedtm',
+                       'cutoff' => 0.75,
+                       'timeout-sync' => 4,
+                       'timeout-async' => 4,
+                       'type' => 'shared-ttmserver',
+               );
+
+       }
+
+       protected function tearDown() {
+               global $wgTranslateTranslationServices;
+               $wgTranslateTranslationServices = $this->config;
+               parent::tearDown();
+       }
+
+       public function testConstruct() {
+               $server = TTMServer::primary();
+               $this->assertEquals(
+                       'FakeTTMServer',
+                       get_class( $server ),
+                       'Fake server given when default server is disabled'
+               );
+               global $wgTranslateTranslationServices;
+               $wgTranslateTranslationServices['TTMServer'] = array(
+                       'database' => false, // Passed to wfGetDB
+                       'cutoff' => 0.75,
+                       'type' => 'ttmserver',
+                       'public' => false,
+               );
+               $server = TTMServer::primary();
+               $this->assertEquals(
+                       'TTMServer',
+                       get_class( $server ),
+                       'Real server given when default server is enabled'
+               );
+               unset( $wgTranslateTranslationServices['TTMServer'] );
+       }
+
+       public function testFakeTTMServer() {
+               $server = new FakeTTMServer();
+               $this->assertEquals(
+                       array(),
+                       $server->query( 'en', 'fi', 'daa' ),
+                       'FakeTTMServer returns no suggestions for all queries'
+               );
+
+               $title = new Title();
+               $handle = new MessageHandle( $title );
+
+               $this->assertFalse(
+                       $server->update( $handle, 'text' ),
+                       'FakeTTMServer returns false on update'
+               );
+
+               $this->assertFalse(
+                       $server->insertSource( $title, 'fi', 'teksti' ),
+                       'FakeTTMServer returns false on insertSource'
+               );
+       }
+
+       /**
+        * @dataProvider dataIsShared
+        */
+       public function testIsShared( $server, $value ) {
+               global $wgTranslateTranslationServices;
+               $server = new TTMServer( 
$wgTranslateTranslationServices[$server] );
+               $this->assertEquals( $value, $server->isShared() );
+       }
+
+       public function dataIsShared() {
+               return array(
+                       array( 'localtm', false ),
+                       array( 'apitm', false ),
+                       array( 'sharedtm', true ),
+               );
+       }
+
+}


Property changes on: trunk/extensions/Translate/tests/TTMServerTest.php
___________________________________________________________________
Added: svn:eol-style
   + native

Modified: trunk/extensions/Translate/utils/TTMServer.php
===================================================================
--- trunk/extensions/Translate/utils/TTMServer.php      2012-03-11 17:26:07 UTC 
(rev 113576)
+++ trunk/extensions/Translate/utils/TTMServer.php      2012-03-11 18:17:27 UTC 
(rev 113577)
@@ -71,6 +71,51 @@
        }
 
        /**
+        * Determines if the suggestion returned by this TTMServer comes
+        * from this wiki or any other wiki.
+        * @return Bool
+        * @since 2012-03-11
+        */
+       public function isLocalSuggestion( array $suggestion ) {
+               $type = $this->config['type'];
+               $isLocal = $type === 'ttmserver';
+               if ( $type === 'shared-ttmserver' && $suggestion['wiki'] === 
wfWikiId() ) {
+                       $isLocal = true;
+               }
+               return $isLocal;
+       }
+
+       /**
+        * Given suggestion returned by this TTMServer, constructs fully
+        * qualified URL to the location of the translation.
+        * @return String URL
+        * @since 2012-03-11
+        */
+       public function expandLocation( array $suggestion ) {
+               $type = $this->config['type'];
+               if ( $type === 'shared-ttmserver' ) {
+                       $wiki = WikiMap::getWiki( $suggestion['wiki'] );
+                       return $wiki->getCanonicalUrl( $suggestion['location'] 
);
+               } elseif ( $type === 'remote-ttmserver' ) {
+                       return $suggestion['location'];
+               } else {
+                       $title = Title::newFromText( $suggestion['location'] );
+                       return $title->getCanonicalUrl();
+               }
+       }
+
+       /**
+        * Is this TTMServer instance using shared translation memory database.
+        * This affects the database layout, shared databases have an extra 
field
+        * and we have to be considerate about data originating from other 
wikies.
+        * @return Bool
+        * @since 2012-03-11
+        */
+       public function isShared() {
+               return $this->config['type'] === 'shared-ttmserver';
+       }
+
+       /**
         * @param $mode int
         * @return DatabaseBase
         */
@@ -111,6 +156,10 @@
                        'tms_context' => $title->getPrefixedText(),
                        'tms_text' => $definition,
                );
+               if ( $this->isShared() ) {
+                       $conds['tms_wiki'] = wfWikiId();
+               }
+
                $sid = $dbw->selectField( 'translate_tms', 'tms_sid', $conds, 
__METHOD__ );
                if ( $sid === false ) {
                        $sid = $this->insertSource( $title, $sourceLanguage, 
$definition );
@@ -142,6 +191,10 @@
                        'tms_context' => $context->getPrefixedText(),
                );
 
+               if ( $this->isShared() ) {
+                       $row['tms_wiki'] = wfWikiId();
+               }
+
                $dbw = $this->getDB( DB_MASTER );
                $dbw->insert( 'translate_tms', $row, __METHOD__ );
                $sid = $dbw->insertId();
@@ -172,6 +225,10 @@
                $dbr = $this->getDB( DB_SLAVE );
                $tables = array( 'translate_tmt', 'translate_tms' );
                $fields = array( 'tms_context', 'tms_text', 'tmt_lang', 
'tmt_text' );
+               if ( $this->isShared() ) {
+                       $fields[] = 'tms_wiki';
+               }
+
                $conds = array(
                        'tms_lang' => $sourceLanguage,
                        'tmt_lang' => $targetLanguage,
@@ -189,10 +246,10 @@
 
                $res = $dbr->select( $tables, $fields, $conds, __METHOD__ );
                wfProfileOut( __METHOD__ );
-               return $this->processQueryResults( $res, $text );
+               return $this->processQueryResults( $res, $text, 
$sourceLanguage, $targetLanguage );
        }
 
-       protected function processQueryResults( $res, $text ) {
+       protected function processQueryResults( $res, $text, $sourceLanguage, 
$targetLanguage ) {
                wfProfileIn( __METHOD__ );
                $lenA = mb_strlen( $text );
                $results = array();
@@ -211,11 +268,14 @@
                        $quality = 1 - ( $dist / $len );
 
                        if ( $quality >= $this->config['cutoff'] ) {
+                               $loc = self::contextToLocation( 
$row->tms_context, $sourceLanguage, $targetLanguage );
                                $results[] = array(
                                        'source' => $row->tms_text,
                                        'target' => $row->tmt_text,
                                        'context' => $row->tms_context,
+                                       'location' => $loc,
                                        'quality' => $quality,
+                                       'wiki' => isset( $row->tms_wiki ) ? 
$row->tms_wiki : false,
                                );
                        }
                }
@@ -265,6 +325,18 @@
        }
 
        /**
+        * Given pagename Namespace:Page/en, replace the language code with
+        * the target language. In theory namespaces could be stored 
differently,
+        * but in MediaWiki this is standard practise.
+        * @return String
+        * @since 2012-03-11
+        */
+       protected static function contextToLocation( $text, $sourceLanguage, 
$targetLanguage ) {
+               $len = strlen( $sourceLanguage );
+               return substr( $text, 0, -$len ) . $targetLanguage;
+       }
+
+       /**
         * The native levenshtein is limited to 255 bytes.
         */
        public static function levenshtein( $str1, $str2, $length1, $length2 ) {

Modified: trunk/extensions/Translate/utils/TranslationHelpers.php
===================================================================
--- trunk/extensions/Translate/utils/TranslationHelpers.php     2012-03-11 
17:26:07 UTC (rev 113576)
+++ trunk/extensions/Translate/utils/TranslationHelpers.php     2012-03-11 
18:17:27 UTC (rev 113577)
@@ -258,7 +258,8 @@
                $source = $this->group->getSourceLanguage();
                $code = $this->handle->getCode();
                $definition = $this->getDefinition();
-               $suggestions = TTMServer::primary()->query( $source, $code, 
$definition );
+               $TTMServer = new TTMServer( $config );
+               $suggestions = $TTMServer->query( $source, $code, $definition );
                if ( count( $suggestions ) === 0 ) {
                        throw new TranslationHelperExpection( 'No suggestions' 
);
                }
@@ -319,34 +320,37 @@
                        $suggestions = $wrapper['suggestions'];
 
                        foreach ( $suggestions as $s ) {
-                               $accuracy = wfMsgHtml( 'translate-edit-tmmatch' 
, sprintf( '%.2f', $s['quality'] * 100 ) );
+                               $tooltip = wfMessage( 
'translate-edit-tmmatch-source', $s['source'] )->plain();
+                               $text = wfMessage( 'translate-edit-tmmatch', 
sprintf( '%.2f', $s['quality'] * 100 ) )->plain();
+                               $accuracy = Html::element( 'span', array( 
'title' => $tooltip ), $text );
                                $legend = array( $accuracy => array() );
 
-                               if ( $config['type'] === 'remote-ttmserver' ) {
+                               $TTMServer = new TTMServer( $config );
+                               if ( $TTMServer->isLocalSuggestion( $s ) ) {
+                                       $title = Title::newFromText( 
$s['location'] );
+                                       $symbol = isset( $config['symbol'] ) ? 
$config['symbol'] : '•';
+                                       $legend[$accuracy][] = 
self::ajaxEditLink( $title, '•' );
+                               } else {
+                                       if ( $config['type'] === 
'remote-ttmserver' ) {
+                                               $displayName = 
$config['displayname'];
+                                       } else {
+                                               $wiki = WikiMap::getWiki( 
$s['wiki'] );
+                                               $displayName = 
$wiki->getDisplayName() . ': ' . $s['location'];
+                                       }
+
                                        $params = array(
-                                               'href' => $url = 
$config['viewurl'] . $s['context'],
+                                               'href' => 
$TTMServer->expandLocation( $s ),
                                                'target' => '_blank',
-                                               'title' => 
"{$config['displayname']}: {$s['context']}",
+                                               'title' => $displayName,
                                        );
-                                       $legend[$accuracy][] = Html::element( 
'a', $params, '‣' );
-                               } else {
-                                       $sourceTitle = Title::newFromText( 
$s['context'] );
-                                       $handle = new MessageHandle( 
$sourceTitle );
-                                       $targetTitle = Title::makeTitle( 
$sourceTitle->getNamespace(), $handle->getKey() . "/$code" );
-                                       if ( $targetTitle ) {
-                                               $legend[$accuracy][] = 
self::ajaxEditLink( $targetTitle, '•' );
-                                       }
+
+                                       $symbol = isset( $config['symbol'] ) ? 
$config['symbol'] : '‣';
+                                       $legend[$accuracy][] = Html::element( 
'a', $params, $symbol );
                                }
 
-                               // Show the source text in a tooltip
-                               if ( isset( $s['target'] ) ) {
-                                       $suggestion = $s['target'];
-                               } else {
-                                       $suggestion = $s['*'];
-                                       
-                               }
+                               $suggestion = $s['target'];
                                $text = $this->suggestionField( $suggestion );
-                               $params = array( 'class' => 
'mw-sp-translate-edit-tmsug', 'title' => $s['source'] );
+                               $params = array( 'class' => 
'mw-sp-translate-edit-tmsug' );
 
                                // Group identical suggestions together
                                if ( isset( $sugFields[$suggestion] ) ) {
@@ -386,6 +390,7 @@
 
                $handlers = array(
                        'ttmserver' => 'getTTMServerBox',
+                       'shared-ttmserver' => 'getTTMServerBox',
                        'remote-ttmserver' => 'getRemoteTTMServerBox',
                        'microsoft' => 'getMicrosoftSuggestion',
                        'apertium'  => 'getApertiumSuggestion',
@@ -395,17 +400,19 @@
                $boxes = array();
                $TTMSSug = array();
                foreach ( $wgTranslateTranslationServices as $name => $config ) 
{
-                       if ( $async === 'async' ) {
-                               $config['timeout'] = $config['timeout-async'];
-                       } else {
-                               $config['timeout'] = $config['timeout-sync'];
+                       $type = $config['type'];
+                       if ( $type !== 'ttmserver' ) {
+                               if ( $async === 'async' ) {
+                                       $config['timeout'] = 
$config['timeout-async'];
+                               } else {
+                                       $config['timeout'] = 
$config['timeout-sync'];
+                               }
                        }
 
-                       $type = $config['type'];
                        if ( isset( $handlers[$type] ) ) {
                                $method = $handlers[$type];
                                try {
-                                       if ( $type === 'ttmserver' || $type === 
'remote-ttmserver' ) {
+                                       if ( $type === 'ttmserver' || $type === 
'remote-ttmserver' || $type === 'shared-ttmserver' ) {
                                                $TTMSSug[$name] = array(
                                                        'config' => $config,
                                                        'suggestions' => 
$this->$method( $name, $config ),


_______________________________________________
MediaWiki-CVS mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to