public function testGetSourceLanguage() {
		$this->assertEquals(
			'en',
			$this->group->getSourceLanguage(),
			"source language defaults to en."
		);
	}
 /**
  * Get the message definition. Cached for performance.
  *
  * @return string
  */
 public function getDefinition()
 {
     static $cache = array();
     $key = $this->handle->getTitle()->getPrefixedText();
     if (array_key_exists($key, $cache)) {
         return $cache[$key];
     }
     if (method_exists($this->group, 'getMessageContent')) {
         $cache[$key] = $this->group->getMessageContent($this->handle);
     } else {
         $cache[$key] = $this->group->getMessage($this->handle->getKey(), $this->group->getSourceLanguage());
     }
     return $cache[$key];
 }
 public function contents()
 {
     $optional = $this->context->msg('translate-optional')->escaped();
     $this->doLinkBatch();
     $sourceLang = Language::factory($this->group->getSourceLanguage());
     $targetLang = Language::factory($this->collection->getLanguage());
     $titleMap = $this->collection->keys();
     $output = '';
     $this->collection->initMessages();
     // Just to be sure
     /**
      * @var TMessage $m
      */
     foreach ($this->collection as $key => $m) {
         $tools = array();
         /**
          * @var Title $title
          */
         $title = $titleMap[$key];
         $original = $m->definition();
         $translation = $m->translation();
         $hasTranslation = $translation !== null;
         if ($hasTranslation) {
             $message = $translation;
             $extraAttribs = self::getLanguageAttributes($targetLang);
         } else {
             $message = $original;
             $extraAttribs = self::getLanguageAttributes($sourceLang);
         }
         Hooks::run('TranslateFormatMessageBeforeTable', array(&$message, $m, $this->group, $targetLang, &$extraAttribs));
         // Using Html::element( a ) because Linker::link is memory hog.
         // It takes about 20 KiB per call, and that times 5000 is quite
         // a lot of memory.
         $niceTitle = htmlspecialchars($this->context->getLanguage()->truncate($title->getPrefixedText(), -35));
         $linkAttribs = array('href' => $title->getLocalUrl(array('action' => 'edit')));
         $linkAttribs += TranslationEditPage::jsEdit($title, $this->group->getId());
         $tools['edit'] = Html::element('a', $linkAttribs, $niceTitle);
         $anchor = 'msg_' . $key;
         $anchor = Xml::element('a', array('id' => $anchor, 'href' => "#{$anchor}"), "↓");
         $extra = '';
         if ($m->hasTag('optional')) {
             $extra = '<br />' . $optional;
         }
         $tqeData = $extraAttribs + array('data-title' => $title->getPrefixedText(), 'data-group' => $this->group->getId(), 'id' => 'tqe-anchor-' . substr(sha1($title->getPrefixedText()), 0, 12), 'class' => 'tqe-inlineeditable ' . ($hasTranslation ? 'translated' : 'untranslated'));
         $button = $this->getReviewButton($m);
         $status = $this->getReviewStatus($m);
         $leftColumn = $button . $anchor . $tools['edit'] . $extra . $status;
         if ($this->reviewMode) {
             $output .= Xml::tags('tr', array('class' => 'orig'), Xml::tags('td', array('rowspan' => '2'), $leftColumn) . Xml::tags('td', self::getLanguageAttributes($sourceLang), TranslateUtils::convertWhiteSpaceToHTML($original)));
             $output .= Xml::tags('tr', null, Xml::tags('td', $tqeData, TranslateUtils::convertWhiteSpaceToHTML($message)));
         } else {
             $output .= Xml::tags('tr', array('class' => 'def'), Xml::tags('td', null, $leftColumn) . Xml::tags('td', $tqeData, TranslateUtils::convertWhiteSpaceToHTML($message)));
         }
         $output .= "\n";
     }
     return $output;
 }
	protected function getTranslationPageDiff() {

		global $wgEnablePageTranslation;

		if ( !$wgEnablePageTranslation ) {
			return null;
		}

		$this->mustBeKnownMessage();
		if ( !$this->group instanceof WikiPageMessageGroup ) {
			return null;
		}

		// Shortcuts
		$code = $this->handle->getCode();
		$key = $this->handle->getKey();

		// TODO: encapsulate somewhere
		$page = TranslatablePage::newFromTitle( $this->group->getTitle() );
		$rev = $page->getTransRev( "$key/$code" );
		$latest = $page->getMarkedTag();
		if ( $rev === $latest ) {
			return null;
		}

		$oldpage = TranslatablePage::newFromRevision( $this->group->getTitle(), $rev );
		$oldtext = $newtext = null;
		foreach ( $oldpage->getParse()->getSectionsForSave() as $section ) {
			if ( $this->group->getTitle()->getPrefixedDBKey() . '/' . $section->id === $key ) {
				$oldtext = $section->getTextForTrans();
			}
		}

		foreach ( $page->getParse()->getSectionsForSave() as $section ) {
			if ( $this->group->getTitle()->getPrefixedDBKey() . '/' . $section->id === $key ) {
				$newtext = $section->getTextForTrans();
			}
		}

		if ( $oldtext === $newtext ) {
			return null;
		}

		$diff = new DifferenceEngine;
		if ( method_exists( 'DifferenceEngine', 'setTextLanguage' ) ) {
			$diff->setTextLanguage( $this->group->getSourceLanguage() );
		}
		$diff->setText( $oldtext, $newtext );
		$diff->setReducedLineNumbers();
		$diff->showDiffStyle();

		return $diff->getDiff( wfMsgHtml( 'tpt-diff-old' ), wfMsgHtml( 'tpt-diff-new' ) );
	}
 protected function getPageDiff()
 {
     $this->mustBeKnownMessage();
     $title = $this->handle->getTitle();
     $key = $this->handle->getKey();
     if (!$title->exists()) {
         return null;
     }
     $definitionTitle = Title::makeTitleSafe($title->getNamespace(), "{$key}/en");
     if (!$definitionTitle || !$definitionTitle->exists()) {
         return null;
     }
     $db = wfGetDB(DB_MASTER);
     $conds = array('rt_page' => $title->getArticleID(), 'rt_type' => RevTag::getType('tp:transver'));
     $options = array('ORDER BY' => 'rt_revision DESC');
     $latestRevision = $definitionTitle->getLatestRevID();
     $translationRevision = $db->selectField('revtag', 'rt_value', $conds, __METHOD__, $options);
     if ($translationRevision === false) {
         return null;
     }
     // Using newFromId instead of newFromTitle, because the page might have been renamed
     $oldrev = Revision::newFromId($translationRevision);
     if (!$oldrev) {
         // And someone might still have deleted it
         return null;
     }
     $oldtext = ContentHandler::getContentText($oldrev->getContent());
     $newContent = Revision::newFromTitle($definitionTitle, $latestRevision)->getContent();
     $newtext = ContentHandler::getContentText($newContent);
     if ($oldtext === $newtext) {
         return null;
     }
     $diff = new DifferenceEngine();
     if (method_exists('DifferenceEngine', 'setTextLanguage')) {
         $diff->setTextLanguage($this->group->getSourceLanguage());
     }
     $oldContent = ContentHandler::makeContent($oldtext, $diff->getTitle());
     $newContent = ContentHandler::makeContent($newtext, $diff->getTitle());
     $diff->setContent($oldContent, $newContent);
     $diff->setReducedLineNumbers();
     $diff->showDiffStyle();
     return $diff->getDiff(wfMessage('tpt-diff-old')->escaped(), wfMessage('tpt-diff-new')->escaped());
 }
 /**
  * @param MessageGroup $group
  * @param string $code
  * @param string $type
  * @param array $params
  * @param int $limit
  * @return string HTML
  */
 protected function formatChange(MessageGroup $group, $code, $type, $params, &$limit)
 {
     $key = $params['key'];
     $title = Title::makeTitleSafe($group->getNamespace(), "{$key}/{$code}");
     $id = self::changeId($group->getId(), $code, $type, $key);
     if ($title && $title->exists() && $type === 'addition') {
         // The message has for some reason dropped out from cache
         // or perhaps it is being reused. In any case treat it
         // as a change for display, so the admin can see if
         // action is needed and let the message be processed.
         // Otherwise it will end up in the postponed category
         // forever and will prevent rebuilding the cache, which
         // leads to many other annoying problems.
         $type = 'change';
     } elseif ($title && !$title->exists() && ($type === 'deletion' || $type === 'change')) {
         return '';
     }
     $text = '';
     if ($type === 'deletion') {
         $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent());
         $oldContent = ContentHandler::makeContent($wiki, $title);
         $newContent = ContentHandler::makeContent('', $title);
         $this->diff->setContent($oldContent, $newContent);
         $text = $this->diff->getDiff(Linker::link($title), '');
     } elseif ($type === 'addition') {
         $oldContent = ContentHandler::makeContent('', $title);
         $newContent = ContentHandler::makeContent($params['content'], $title);
         $this->diff->setContent($oldContent, $newContent);
         $text = $this->diff->getDiff('', Linker::link($title));
     } elseif ($type === 'change') {
         $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent());
         $handle = new MessageHandle($title);
         if ($handle->isFuzzy()) {
             $wiki = '!!FUZZY!!' . str_replace(TRANSLATE_FUZZY, '', $wiki);
         }
         $label = $this->msg('translate-manage-action-ignore')->text();
         $actions = Xml::checkLabel($label, "i/{$id}", "i/{$id}");
         $limit--;
         if ($group->getSourceLanguage() === $code) {
             $label = $this->msg('translate-manage-action-fuzzy')->text();
             $actions .= ' ' . Xml::checkLabel($label, "f/{$id}", "f/{$id}", true);
             $limit--;
         }
         $oldContent = ContentHandler::makeContent($wiki, $title);
         $newContent = ContentHandler::makeContent($params['content'], $title);
         $this->diff->setContent($oldContent, $newContent);
         $text .= $this->diff->getDiff(Linker::link($title), $actions);
     }
     $hidden = Html::hidden($id, 1);
     $limit--;
     $text .= $hidden;
     $classes = "mw-translate-smg-change smg-change-{$type}";
     if ($limit < 0) {
         // Don't add if one of the fields might get dropped of at submission
         return '';
     }
     return Html::rawElement('div', array('class' => $classes), $text);
 }
 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();
     $id = $group->getId();
     $sourceLanguage = $group->getSourceLanguage();
     if ($multi) {
         $stats = MessageGroupStats::forGroup($id);
         $this->statusLine("Loaded stats for {$id}\n");
     } else {
         $this->statusLine("Loading stats... ", 4);
         $stats = MessageGroupStats::forGroup($id);
         $this->output("done!", 4);
         $this->statusLine("Inserting sources: ", 5);
     }
     $collection = $group->initCollection($sourceLanguage);
     $collection->filter('ignored');
     $collection->filter('optional');
     $collection->initMessages();
     $sids = array();
     $counter = 0;
     foreach ($collection->keys() as $mkey => $title) {
         $def = $collection[$mkey]->definition();
         $sids[$mkey] = $server->insertSource($title, $sourceLanguage, $def);
         if (++$counter % $this->mBatchSize === 0 && !$multi) {
             wfWaitForSlaves(10);
             $this->output('.', 5);
         }
     }
     $total = count($sids);
     if ($multi) {
         $this->statusLine("Inserted {$total} source entries for {$id}\n");
     } else {
         $this->output("{$total} entries", 5);
         $this->statusLine("Inserting translations...", 6);
     }
     $dbw = $server->getDB(DB_MASTER);
     foreach ($stats as $targetLanguage => $numbers) {
         if ($targetLanguage === $sourceLanguage) {
             continue;
         }
         if ($numbers[MessageGroupStats::TRANSLATED] === 0) {
             continue;
         }
         if (!$multi) {
             $this->output(sprintf("%19s  ", $targetLanguage), $targetLanguage);
         }
         $collection->resetForNewLanguage($targetLanguage);
         $collection->filter('ignored');
         $collection->filter('optional');
         $collection->filter('translated', false);
         $collection->loadTranslations();
         $inserts = array();
         foreach ($collection->keys() as $mkey => $title) {
             $inserts[] = array('tmt_sid' => $sids[$mkey], 'tmt_lang' => $targetLanguage, 'tmt_text' => $collection[$mkey]->translation());
         }
         do {
             $batch = array_splice($inserts, 0, $this->mBatchSize);
             $dbw->insert('translate_tmt', $batch, __METHOD__);
             if (!$multi) {
                 $this->output('.', $targetLanguage);
             }
             wfWaitForSlaves(10);
         } while (count($inserts));
     }
     if ($multi) {
         $this->statusLine("Inserted translations for {$id}\n");
     }
 }
 protected function exportGroup(MessageGroup $group, $config)
 {
     $server = TTMServer::factory($config);
     $server->setLogger($this);
     $id = $group->getId();
     $sourceLanguage = $group->getSourceLanguage();
     $stats = MessageGroupStats::forGroup($id);
     $collection = $group->initCollection($sourceLanguage);
     $collection->filter('ignored');
     $collection->initMessages();
     $server->beginBatch();
     $inserts = array();
     foreach ($collection->keys() as $mkey => $title) {
         $handle = new MessageHandle($title);
         $inserts[] = array($handle, $sourceLanguage, $collection[$mkey]->definition());
     }
     while ($inserts !== array()) {
         $batch = array_splice($inserts, 0, $this->mBatchSize);
         $server->batchInsertDefinitions($batch);
     }
     $inserts = array();
     foreach ($stats as $targetLanguage => $numbers) {
         if ($targetLanguage === $sourceLanguage) {
             continue;
         }
         if ($numbers[MessageGroupStats::TRANSLATED] === 0) {
             continue;
         }
         $collection->resetForNewLanguage($targetLanguage);
         $collection->filter('ignored');
         $collection->filter('translated', false);
         $collection->loadTranslations();
         foreach ($collection->keys() as $mkey => $title) {
             $handle = new MessageHandle($title);
             $inserts[] = array($handle, $sourceLanguage, $collection[$mkey]->translation());
         }
         while (count($inserts) >= $this->mBatchSize) {
             $batch = array_splice($inserts, 0, $this->mBatchSize);
             $server->batchInsertTranslations($batch);
         }
     }
     while ($inserts !== array()) {
         $batch = array_splice($inserts, 0, $this->mBatchSize);
         $server->batchInsertTranslations($batch);
     }
     $server->endBatch();
 }