public function execute()
 {
     $params = $this->extractRequestParams();
     $title = Title::newFromText($params['title']);
     if (!$title) {
         $this->dieUsage('Invalid title', 'invalidtitle');
     }
     $handle = new MessageHandle($title);
     if (!$handle->isValid()) {
         $this->dieUsage('Title does not correspond to a translatable message', 'nomessagefortitle');
     }
     if (strval($params['group']) !== '') {
         $group = MessageGroups::getGroup($params['group']);
     } else {
         $group = $handle->getGroup();
     }
     if (!$group) {
         $this->dieUsage('Invalid group', 'invalidgroup');
     }
     $data = array();
     $times = array();
     $props = $params['prop'];
     $aggregator = new QueryAggregator();
     // Figure out the intersection of supported and requested aids
     $types = $group->getTranslationAids();
     $props = array_intersect($props, array_keys($types));
     $result = $this->getResult();
     // Create list of aids, populate web services queries
     $aids = array();
     foreach ($props as $type) {
         $class = $types[$type];
         $obj = new $class($group, $handle, $this);
         if ($obj instanceof QueryAggregatorAware) {
             $obj->setQueryAggregator($aggregator);
             $obj->populateQueries();
         }
         $aids[$type] = $obj;
     }
     // Execute all web service queries asynchronously to save time
     $start = microtime(true);
     $aggregator->run();
     $times['query_aggregator'] = round(microtime(true) - $start, 3);
     // Construct the result data structure
     foreach ($aids as $type => $obj) {
         $start = microtime(true);
         try {
             $aid = $obj->getData();
         } catch (TranslationHelperException $e) {
             $aid = array('error' => $e->getMessage());
         }
         if (isset($aid['**'])) {
             $result->setIndexedTagName($aid, $aid['**']);
             unset($aid['**']);
         }
         $data[$type] = $aid;
         $times[$type] = round(microtime(true) - $start, 3);
     }
     $result->addValue(null, 'helpers', $data);
     $result->addValue(null, 'times', $times);
 }
 public function testParsing()
 {
     $title = Title::newFromText('MediaWiki:Ugakey/nl');
     $page = WikiPage::factory($title);
     $content = ContentHandler::makeContent('$1 van $2', $title);
     $status = $page->doEditContent($content, __METHOD__);
     $value = $status->getValue();
     /**
      * @var Revision $rev
      */
     $rev = $value['revision'];
     $revision = $rev->getId();
     $dbw = wfGetDB(DB_MASTER);
     $conds = array('rt_page' => $title->getArticleID(), 'rt_type' => RevTag::getType('fuzzy'), 'rt_revision' => $revision);
     $index = array_keys($conds);
     $dbw->replace('revtag', array($index), $conds, __METHOD__);
     $handle = new MessageHandle($title);
     $this->assertTrue($handle->isValid(), 'Message is known');
     $this->assertTrue($handle->isFuzzy(), 'Message is fuzzy after database fuzzying');
     // Update the translation without the fuzzy string
     $content = ContentHandler::makeContent('$1 van $2', $title);
     $page->doEditContent($content, __METHOD__);
     $this->assertFalse($handle->isFuzzy(), 'Message is unfuzzy after edit');
     $content = ContentHandler::makeContent('!!FUZZY!!$1 van $2', $title);
     $page->doEditContent($content, __METHOD__);
     $this->assertTrue($handle->isFuzzy(), 'Message is fuzzy after manual fuzzying');
     // Update the translation without the fuzzy string
     $content = ContentHandler::makeContent('$1 van $2', $title);
     $page->doEditContent($content, __METHOD__);
     $this->assertFalse($handle->isFuzzy(), 'Message is unfuzzy after edit');
 }
	public function execute() {
		global $wgUser;
		if ( !$wgUser->isallowed( self::$right ) ) {
			$this->dieUsage( 'Permission denied', 'permissiondenied' );
		}

		$params = $this->extractRequestParams();

		$revision = Revision::newFromId( $params['revision'] );
		if ( !$revision ) {
			$this->dieUsage( 'Invalid revision', 'invalidrevision' );
		}

		$title = $revision->getTitle();
		$handle = new MessageHandle( $title );
		if ( !$handle->isValid() ) {
			$this->dieUsage( 'Unknown message', 'unknownmessage' );
		}

		if ( $handle->isFuzzy() ) {
			$this->dieUsage( 'Cannot review fuzzy translations', 'fuzzymessage' );
		}

		if ( $revision->getUser() == $wgUser->getId() ) {
			$this->dieUsage( 'Cannot review own translations', 'owntranslation' );
		}

		$dbw = wfGetDB( DB_MASTER );
		$table = 'translate_reviews';
		$row = array(
			'trr_user' => $wgUser->getId(),
			'trr_page' => $revision->getPage(),
			'trr_revision' => $revision->getId(),
		);
		$options = array( 'IGNORE' );
		$res = $dbw->insert( $table, $row, __METHOD__, $options );
		if ( !$dbw->affectedRows() ) {
			$this->setWarning( 'Already marked as reviewed by you' );
		} else {
			$logger = new LogPage( 'translationreview' );
			$params = array( $revision->getId() );
			$logger->addEntry( 'message', $title, null, $params, $wgUser );
		}

		$output = array( 'review' => array(
			'title' => $title->getPrefixedText(),
			'pageid' => $revision->getPage(),
			'revision' => $revision->getId()
		) );

		$this->getResult()->addValue( null, $this->getModuleName(), $output );
	}
 /**
  * Adds link in toolbox to Special:Prefixindex to show all other
  * available translations for a message. Only shown when it
  * actually is a translatable/translated message.
  *
  * @param $quickTemplate QuickTemplate
  *
  * @return bool
  */
 static function toolboxAllTranslations(&$quickTemplate)
 {
     $title = $quickTemplate->getSkin()->getTitle();
     $handle = new MessageHandle($title);
     if ($handle->isValid()) {
         $message = $title->getNsText() . ':' . $handle->getKey();
         $desc = wfMessage('translate-sidebar-alltrans')->escaped();
         $url = htmlspecialchars(SpecialPage::getTitleFor('Translations')->getLocalURL(array('message' => $message)));
         // Add the actual toolbox entry.
         // Add newlines and tabs for nicer HTML output.
         echo "\n\t\t\t\t<li id=\"t-alltrans\"><a href=\"{$url}\">{$desc}</a></li>\n";
     }
     return true;
 }
 protected function formatTranslation(StashedTranslation $translation)
 {
     $title = $translation->getTitle();
     $handle = new MessageHandle($title);
     // Prepare for the worst
     $definition = '';
     $comparison = '';
     if ($handle->isValid()) {
         $groupId = MessageIndex::getPrimaryGroupId($handle);
         $group = MessageGroups::getGroup($groupId);
         $key = $handle->getKey();
         $definition = $group->getMessage($key, $group->getSourceLanguage());
         $comparison = $group->getMessage($key, $handle->getCode());
     }
     return array('title' => $title->getPrefixedText(), 'definition' => $definition, 'translation' => $translation->getValue(), 'comparison' => $comparison, 'metadata' => $translation->getMetadata());
 }
 protected function extractMessages($resultset, $offset, $limit)
 {
     $messages = $documents = $ret = array();
     $language = $this->params['language'];
     foreach ($resultset->getResults() as $document) {
         $data = $document->getData();
         if (!$this->server->isLocalSuggestion($data)) {
             continue;
         }
         $title = Title::newFromText($data['localid']);
         if (!$title) {
             continue;
         }
         $handle = new MessageHandle($title);
         if (!$handle->isValid()) {
             continue;
         }
         $key = $title->getNamespace() . ':' . $title->getDBKey();
         $messages[$key] = $data['content'];
     }
     $definitions = new MessageDefinitions($messages);
     $collection = MessageCollection::newFromDefinitions($definitions, $language);
     $filter = $this->params['filter'];
     if ($filter === 'untranslated') {
         $collection->filter('hastranslation', true);
     } elseif (in_array($filter, $this->getAvailableFilters())) {
         $collection->filter($filter, false);
     }
     $total = count($collection);
     $offset = $collection->slice($offset, $limit);
     $left = count($collection);
     $offsets = array('start' => $offset[2], 'left' => $left, 'total' => $total);
     if ($filter === 'translated' || $filter === 'fuzzy') {
         $collection->loadTranslations();
     }
     foreach ($collection->keys() as $mkey => $title) {
         $documents[$mkey]['content'] = $messages[$mkey];
         if ($filter === 'translated' || $filter === 'fuzzy') {
             $documents[$mkey]['content'] = $collection[$mkey]->translation();
         }
         $handle = new MessageHandle($title);
         $documents[$mkey]['localid'] = $handle->getTitleForBase()->getPrefixedText();
         $documents[$mkey]['language'] = $language;
         $ret[] = $documents[$mkey];
     }
     return array($ret, $offsets);
 }
 public function execute()
 {
     $params = $this->extractRequestParams();
     $title = Title::newFromText($params['title']);
     if (!$title) {
         $this->dieUsage('Invalid title');
     }
     $handle = new MessageHandle($title);
     if (!$handle->isValid()) {
         $this->dieUsage('Title does not correspond to a translatable message');
     }
     $base = Title::makeTitle($title->getNamespace(), $handle->getKey());
     $namespace = $base->getNamespace();
     $message = $base->getDBKey();
     $dbr = wfGetDB(DB_SLAVE);
     $res = $dbr->select('page', array('page_namespace', 'page_title'), array('page_namespace' => $namespace, 'page_title ' . $dbr->buildLike("{$message}/", $dbr->anyString())), __METHOD__, array('ORDER BY' => 'page_title', 'USE INDEX' => 'name_title'));
     $titles = array();
     foreach ($res as $row) {
         $titles[] = $row->page_title;
     }
     $pageInfo = TranslateUtils::getContents($titles, $namespace);
     $result = $this->getResult();
     $pages = array();
     $count = 0;
     foreach ($pageInfo as $key => $info) {
         if (++$count <= $params['offset']) {
             continue;
         }
         $tTitle = Title::makeTitle($namespace, $key);
         $tHandle = new MessageHandle($tTitle);
         $data = array('title' => $tTitle->getPrefixedText(), 'language' => $tHandle->getCode(), 'lasttranslator' => $info[1]);
         $fuzzy = MessageHandle::hasFuzzyString($info[0]) || $tHandle->isFuzzy();
         if ($fuzzy) {
             $data['fuzzy'] = 'fuzzy';
         }
         $translation = str_replace(TRANSLATE_FUZZY, '', $info[0]);
         $result->setContent($data, $translation);
         $fit = $result->addValue(array('query', $this->getModuleName()), null, $data);
         if (!$fit) {
             $this->setContinueEnumParameter('offset', $count);
             break;
         }
     }
     $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'message');
 }
 public function execute()
 {
     $params = $this->extractRequestParams();
     $title = Title::newFromText($params['title']);
     if (!$title) {
         $this->dieUsage('Invalid title', 'invalidtitle');
     }
     $handle = new MessageHandle($title);
     if (!$handle->isValid()) {
         $this->dieUsage('Title does not correspond to a translatable message', 'nomessagefortitle');
     }
     $namespace = $title->getNamespace();
     $pageInfo = self::getTranslations($handle);
     $result = $this->getResult();
     $count = 0;
     foreach ($pageInfo as $key => $info) {
         if (++$count <= $params['offset']) {
             continue;
         }
         $tTitle = Title::makeTitle($namespace, $key);
         $tHandle = new MessageHandle($tTitle);
         $data = array('title' => $tTitle->getPrefixedText(), 'language' => $tHandle->getCode(), 'lasttranslator' => $info[1]);
         $fuzzy = MessageHandle::hasFuzzyString($info[0]) || $tHandle->isFuzzy();
         if ($fuzzy) {
             $data['fuzzy'] = 'fuzzy';
         }
         $translation = str_replace(TRANSLATE_FUZZY, '', $info[0]);
         if (defined('ApiResult::META_CONTENT')) {
             ApiResult::setContentValue($data, 'translation', $translation);
         } else {
             ApiResult::setContent($data, $translation);
         }
         $fit = $result->addValue(array('query', $this->getModuleName()), null, $data);
         if (!$fit) {
             $this->setContinueEnumParameter('offset', $count);
             break;
         }
     }
     if (defined('ApiResult::META_CONTENT')) {
         $result->addIndexedTagName(array('query', $this->getModuleName()), 'message');
     } else {
         $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'message');
     }
 }
 public function run()
 {
     $title = $this->title;
     $handle = new MessageHandle($title);
     $code = $handle->getCode();
     if (!$handle->isValid() && !$code) {
         return true;
     }
     $groups = self::getGroupsWithTransitions($handle);
     foreach ($groups as $id => $transitions) {
         $group = MessageGroups::getGroup($id);
         $stats = MessageGroupStats::forItem($id, $code);
         $state = self::getNewState($stats, $transitions);
         if ($state) {
             ApiGroupReview::changeState($group, $code, $state, FuzzyBot::getUser());
         }
     }
     return true;
 }
 public function update(MessageHandle $handle, $targetText)
 {
     if (!$handle->isValid() || $handle->getCode() === '') {
         return false;
     }
     $mkey = $handle->getKey();
     $group = $handle->getGroup();
     $targetLanguage = $handle->getCode();
     $sourceLanguage = $group->getSourceLanguage();
     // Skip definitions to not slow down mass imports etc.
     // These will be added when the first translation is made
     if ($targetLanguage === $sourceLanguage) {
         return false;
     }
     $definition = $group->getMessage($mkey, $sourceLanguage);
     if (!is_string($definition) || !strlen(trim($definition))) {
         return false;
     }
     $context = Title::makeTitle($handle->getTitle()->getNamespace(), $mkey);
     $dbw = $this->getDB(DB_MASTER);
     /* Check that the definition exists and fetch the sid. If not, add
      * the definition and retrieve the sid. If the definition changes,
      * we will create a new entry - otherwise we could at some point
      * get suggestions which do not match the original definition any
      * longer. The old translations are still kept until purged by
      * rerunning the bootstrap script. */
     $conds = array('tms_context' => $context->getPrefixedText(), 'tms_text' => $definition);
     $sid = $dbw->selectField('translate_tms', 'tms_sid', $conds, __METHOD__);
     if ($sid === false) {
         $sid = $this->insertSource($context, $sourceLanguage, $definition);
     }
     // Delete old translations for this message if any. Could also use replace
     $deleteConds = array('tmt_sid' => $sid, 'tmt_lang' => $targetLanguage);
     $dbw->delete('translate_tmt', $deleteConds, __METHOD__);
     // Insert the new translation
     if ($targetText !== null) {
         $row = $deleteConds + array('tmt_text' => $targetText);
         $dbw->insert('translate_tmt', $row, __METHOD__);
     }
     return true;
 }
 /**
  * Hook to update source and destination translation pages on moving translation units
  * Hook: TitleMoveComplete
  * @since 2014.08
  */
 public static function onMoveTranslationUnits(Title &$ot, Title &$nt, User &$user, $oldid, $newid, $reason)
 {
     // Do the update only once. In case running by job queue, the update is not done here
     if (self::$jobQueueRunning) {
         return;
     }
     $groupLast = null;
     foreach (array($ot, $nt) as $title) {
         $handle = new MessageHandle($title);
         if (!$handle->isValid()) {
             continue;
         }
         // Documentation pages are never translation pages
         if ($handle->isDoc()) {
             continue;
         }
         $group = $handle->getGroup();
         if (!$group instanceof WikiPageMessageGroup) {
             continue;
         }
         $language = $handle->getCode();
         // Ignore pages such as Translations:Page/unit without language code
         if (strval($code) === '') {
             continue;
         }
         // Update the page only once if source and destination units
         // belong to the same page
         if ($group !== $groupLast) {
             $groupLast = $group;
             $page = TranslatablePage::newFromTitle($group->getTitle());
             self::updateTranslationPage($page, $language, $user, 0, $reason);
         }
     }
 }
예제 #12
0
 public function getDefinitions()
 {
     global $wgTranslateMessageNamespaces;
     $db = wfGetDB(DB_SLAVE);
     $tables = 'recentchanges';
     $fields = array('rc_namespace', 'rc_title');
     $conds = array('rc_title ' . $db->buildLike($db->anyString(), '/' . $this->language), 'rc_namespace' => $wgTranslateMessageNamespaces, 'rc_type != ' . RC_LOG, 'rc_id > ' . $this->getRCCutoff());
     $options = array('ORDER BY' => 'rc_id DESC', 'LIMIT' => 1000);
     $res = $db->select($tables, $fields, $conds, __METHOD__, $options);
     $defs = array();
     foreach ($res as $row) {
         $title = Title::makeTitle($row->rc_namespace, $row->rc_title);
         $handle = new MessageHandle($title);
         if (!$handle->isValid()) {
             continue;
         }
         $mkey = $row->rc_namespace . ':' . $handle->getKey();
         if (!isset($defs[$mkey])) {
             $group = $handle->getGroup();
             $defs[$mkey] = $group->getMessage($handle->getKey(), $this->getSourceLanguage());
         }
     }
     return $defs;
 }
 /**
  * Validates review action by checking permissions and other things.
  * @param User $user
  * @param Revision $revision
  * @return string Error key or empty string if review is allowed.
  * @since 2012-09-24
  */
 public static function getReviewBlockers(User $user, Revision $revision)
 {
     if (!$user->isAllowed(self::$right)) {
         return 'permissiondenied';
     }
     if ($user->isBlocked()) {
         return 'blocked';
     }
     $title = $revision->getTitle();
     $handle = new MessageHandle($title);
     if (!$handle->isValid()) {
         return 'unknownmessage';
     }
     if ($revision->getUser() == $user->getId()) {
         return 'owntranslation';
     }
     if ($handle->isFuzzy()) {
         return 'fuzzymessage';
     }
     return '';
 }
 /**
  * Hook: ArticleContentOnDiff
  */
 public static function displayOnDiff(DifferenceEngine $de, OutputPage $out)
 {
     $title = $de->getTitle();
     $handle = new MessageHandle($title);
     if (!$handle->isValid()) {
         return true;
     }
     $th = new TranslationHelpers($title, false);
     $th->setEditMode(false);
     $de->loadNewText();
     if ($de->mNewContent instanceof TextContent) {
         $th->setTranslation($de->mNewContent->getNativeData());
     } else {
         // Screw you, not interested.
         return true;
     }
     TranslationHelpers::addModules($out);
     $boxes = array();
     $boxes[] = $th->callBox('documentation', array($th, 'getDocumentationBox'));
     $boxes[] = $th->callBox('definition', array($th, 'getDefinitionBox'));
     $boxes[] = $th->callBox('translation', array($th, 'getTranslationDisplayBox'));
     $output = implode("\n", $boxes);
     $output = Html::rawElement('div', array('class' => 'mw-sp-translate-edit-fields'), $output);
     $out->addHtml($output);
     return true;
 }
 /**
  * Filters out messages that should not be translated under normal
  * conditions.
  *
  * @param MessageHandle $handle Handle for the translation target.
  * @return boolean
  * @since 2013.10
  */
 public static function isTranslatableMessage(MessageHandle $handle)
 {
     static $cache = array();
     if (!$handle->isValid()) {
         return false;
     }
     $group = $handle->getGroup();
     $groupId = $group->getId();
     $language = $handle->getCode();
     $cacheKey = "{$groupId}:{$language}";
     if (!isset($cache[$cacheKey])) {
         $allowed = true;
         $discouraged = false;
         $whitelist = $group->getTranslatableLanguages();
         if (is_array($whitelist) && !isset($whitelist[$language])) {
             $allowed = false;
         }
         if (self::getPriority($group) === 'discouraged') {
             $discouraged = true;
         } else {
             $priorityLanguages = TranslateMetadata::get($groupId, 'prioritylangs');
             if ($priorityLanguages) {
                 $map = array_flip(explode(',', $priorityLanguages));
                 if (!isset($map[$language])) {
                     $discouraged = true;
                 }
             }
         }
         $cache[$cacheKey] = array('relevant' => $allowed && !$discouraged, 'tags' => array());
         $groupTags = $group->getTags();
         foreach (array('ignored', 'optional') as $tag) {
             if (isset($groupTags[$tag])) {
                 foreach ($groupTags[$tag] as $key) {
                     // TODO: ucfirst should not be here
                     $cache[$cacheKey]['tags'][ucfirst($key)] = true;
                 }
             }
         }
     }
     return $cache[$cacheKey]['relevant'] && !isset($cache[$cacheKey]['tags'][ucfirst($handle->getKey())]);
 }
 public function execute($par)
 {
     global $wgLanguageCode;
     $this->setHeaders();
     $this->checkPermissions();
     $server = TTMServer::primary();
     if (!$server instanceof SearchableTTMServer) {
         throw new ErrorPageError('tux-sst-nosolr-title', 'tux-sst-nosolr-body');
     }
     $out = $this->getOutput();
     $out->addModuleStyles('jquery.uls.grid');
     $out->addModuleStyles('ext.translate.special.searchtranslations.styles');
     $out->addModuleStyles('ext.translate.special.translate.styles');
     $out->addModules('ext.translate.special.searchtranslations');
     $out->addModules('ext.translate.special.searchtranslations.operatorsuggest');
     TranslateUtils::addSpecialHelpLink($out, 'Help:Extension:Translate#searching');
     $this->opts = $opts = new FormOptions();
     $opts->add('query', '');
     $opts->add('sourcelanguage', $wgLanguageCode);
     $opts->add('language', '');
     $opts->add('group', '');
     $opts->add('grouppath', '');
     $opts->add('filter', '');
     $opts->add('match', '');
     $opts->add('case', '');
     $opts->add('limit', $this->limit);
     $opts->add('offset', 0);
     $opts->fetchValuesFromRequest($this->getRequest());
     $queryString = $opts->getValue('query');
     if ($queryString === '') {
         $this->showEmptySearch();
         return;
     }
     $params = $opts->getAllValues();
     $filter = $opts->getValue('filter');
     try {
         $translationSearch = new CrossLanguageTranslationSearchQuery($params, $server);
         if (in_array($filter, $translationSearch->getAvailableFilters())) {
             if ($opts->getValue('language') === '') {
                 $params['language'] = $this->getLanguage()->getCode();
                 $opts->setValue('language', $params['language']);
             }
             $documents = $translationSearch->getDocuments();
             $total = $translationSearch->getTotalHits();
             $resultset = $translationSearch->getResultSet();
         } else {
             $resultset = $server->search($queryString, $params, $this->hl);
             $documents = $server->getDocuments($resultset);
             $total = $server->getTotalHits($resultset);
         }
     } catch (TTMServerException $e) {
         error_log('Translation search server unavailable:' . $e->getMessage());
         throw new ErrorPageError('tux-sst-solr-offline-title', 'tux-sst-solr-offline-body');
     }
     // Part 1: facets
     $facets = $server->getFacets($resultset);
     $facetHtml = '';
     if (count($facets['language']) > 0) {
         if ($filter !== '') {
             $facets['language'] = array_merge($facets['language'], array($opts->getValue('language') => $total));
         }
         $facetHtml = Html::element('div', array('class' => 'row facet languages', 'data-facets' => FormatJson::encode($this->getLanguages($facets['language'])), 'data-language' => $opts->getValue('language')), $this->msg('tux-sst-facet-language'));
     }
     if (count($facets['group']) > 0) {
         $facetHtml .= Html::element('div', array('class' => 'row facet groups', 'data-facets' => FormatJson::encode($this->getGroups($facets['group'])), 'data-group' => $opts->getValue('group')), $this->msg('tux-sst-facet-group'));
     }
     // Part 2: results
     $resultsHtml = '';
     $title = Title::newFromText($queryString);
     if ($title && !in_array($filter, $translationSearch->getAvailableFilters())) {
         $handle = new MessageHandle($title);
         $code = $handle->getCode();
         $language = $opts->getValue('language');
         if ($handle->isValid() && $code !== '' && $code !== $language) {
             $groupId = $handle->getGroup()->getId();
             $helpers = new TranslationHelpers($title, $groupId);
             $document['wiki'] = wfWikiId();
             $document['localid'] = $handle->getTitleForBase()->getPrefixedText();
             $document['content'] = $helpers->getTranslation();
             $document['language'] = $handle->getCode();
             array_unshift($documents, $document);
             $total++;
         }
     }
     foreach ($documents as $document) {
         $text = $document['content'];
         $text = TranslateUtils::convertWhiteSpaceToHTML($text);
         list($pre, $post) = $this->hl;
         $text = str_replace($pre, '<strong class="tux-search-highlight">', $text);
         $text = str_replace($post, '</strong>', $text);
         $title = Title::newFromText($document['localid'] . '/' . $document['language']);
         if (!$title) {
             // Should not ever happen but who knows...
             continue;
         }
         $resultAttribs = array('class' => 'row tux-message', 'data-title' => $title->getPrefixedText(), 'data-language' => $document['language']);
         $handle = new MessageHandle($title);
         if ($handle->isValid()) {
             $groupId = $handle->getGroup()->getId();
             $helpers = new TranslationHelpers($title, $groupId);
             $resultAttribs['data-definition'] = $helpers->getDefinition();
             $resultAttribs['data-translation'] = $helpers->getTranslation();
             $resultAttribs['data-group'] = $groupId;
             $uri = $title->getLocalUrl(array('action' => 'edit'));
             $link = Html::element('a', array('href' => $uri), $this->msg('tux-sst-edit')->text());
         } else {
             $url = wfParseUrl($document['uri']);
             $domain = $url['host'];
             $link = Html::element('a', array('href' => $document['uri']), $this->msg('tux-sst-view-foreign', $domain)->text());
         }
         $access = Html::rawElement('div', array('class' => 'row tux-edit tux-message-item'), $link);
         $titleText = $title->getPrefixedText();
         $titleAttribs = array('class' => 'row tux-title', 'dir' => 'ltr');
         $textAttribs = array('class' => 'row tux-text', 'lang' => wfBCP47($document['language']), 'dir' => Language::factory($document['language'])->getDir());
         $resultsHtml = $resultsHtml . Html::openElement('div', $resultAttribs) . Html::rawElement('div', $textAttribs, $text) . Html::element('div', $titleAttribs, $titleText) . $access . Html::closeElement('div');
     }
     $resultsHtml .= Html::rawElement('hr', array('class' => 'tux-pagination-line'));
     $prev = $next = '';
     $offset = $this->opts->getValue('offset');
     $params = $this->opts->getChangedValues();
     if ($total - $offset > $this->limit) {
         $newParams = array('offset' => $offset + $this->limit) + $params;
         $attribs = array('class' => 'mw-ui-button pager-next', 'href' => $this->getPageTitle()->getLocalUrl($newParams));
         $next = Html::element('a', $attribs, $this->msg('tux-sst-next')->text());
     }
     if ($offset) {
         $newParams = array('offset' => max(0, $offset - $this->limit)) + $params;
         $attribs = array('class' => 'mw-ui-button pager-prev', 'href' => $this->getPageTitle()->getLocalUrl($newParams));
         $prev = Html::element('a', $attribs, $this->msg('tux-sst-prev')->text());
     }
     $resultsHtml .= Html::rawElement('div', array('class' => 'tux-pagination-links'), "{$prev} {$next}");
     $search = $this->getSearchInput($queryString);
     $count = $this->msg('tux-sst-count')->numParams($total);
     $this->showSearch($search, $count, $facetHtml, $resultsHtml, $total);
 }
 public function getDefinitions()
 {
     if (!$this->language) {
         throw new MWException("Language not set");
     }
     $db = wfGetDB(DB_SLAVE);
     $tables = 'recentchanges';
     $fields = array('rc_namespace', 'rc_title');
     $conds = $this->getQueryConditions();
     $options = array('ORDER BY' => 'rc_id DESC', 'LIMIT' => 5000);
     $res = $db->select($tables, $fields, $conds, __METHOD__, $options);
     $defs = array();
     foreach ($res as $row) {
         $title = Title::makeTitle($row->rc_namespace, $row->rc_title);
         $handle = new MessageHandle($title);
         if (!$handle->isValid() || !$this->matchingMessage($handle)) {
             continue;
         }
         $messageKey = $handle->getKey();
         $fullKey = $row->rc_namespace . ':' . $messageKey;
         /* Note: due to bugs, getMessage might return null even for
          * known messages. These negatives are not cached, but that
          * should be rare enough case to not affect performance. */
         if (!isset($defs[$fullKey])) {
             $group = $handle->getGroup();
             $msg = $group->getMessage($messageKey, $group->getSourceLanguage());
             if ($msg !== null) {
                 $defs[$fullKey] = $msg;
             }
         }
     }
     return $defs;
 }
	/**
	 * Hook: ArticleContentOnDiff
	 */
	public static function displayOnDiff( DifferenceEngine $de, OutputPage $out ) {
		$title = $de->getTitle();
		$handle = new MessageHandle( $title );

		if ( !$handle->isValid() ) {
			return true;
		}

		$de->loadNewText();
		$out->setRevisionId( $de->mNewRev->getId() );

		$th = new TranslationHelpers( $title, /*group*/false );
		$th->setEditMode( false );
		$th->setTranslation( $de->mNewtext );
		TranslationHelpers::addModules( $out );

		$boxes = array();
		$boxes[] = $th->getDocumentationBox();
		$boxes[] = $th->getDefinitionBox();
		$boxes[] = $th->getTranslationDisplayBox();

		$output = Html::rawElement( 'div', array( 'class' => 'mw-sp-translate-edit-fields' ), implode( "\n\n", $boxes ) );
		$out->addHtml( $output );

		return false;
	}
예제 #19
0
 /**
  * Prevent editing of unknown pages in Translations namespace.
  * Hook: getUserPermissionsErrorsExpensive
  */
 public static function preventUnknownTranslations(Title $title, User $user, $action, &$result)
 {
     $handle = new MessageHandle($title);
     if ($handle->isPageTranslation() && $action === 'edit' && !$handle->isValid()) {
         $result = array('tpt-unknown-page');
         return false;
     }
     return true;
 }
	/**
	 * Parser function hook
	 */
	public static function translationDialogMagicWord( Parser $parser, $title = '', $linktext = '' ) {
		$title = Title::newFromText( $title );
		if ( !$title ) return '';
		$handle = new MessageHandle( $title );
		if ( !$handle->isValid() ) return '';
		$group = $handle->getGroup();
		$callParams = array( $title->getPrefixedText(), $group->getId() );
		$call = Xml::encodeJsCall( 'mw.translate.openDialog', $callParams );
		$js = <<<JAVASCRIPT
mw.loader.using( 'ext.translate.quickedit', function() { $call; } ); return false;
JAVASCRIPT;

		$a = array(
			'href' => $title->getFullUrl( array( 'action' => 'edit' ) ),
			'onclick' => $js,
		);

		if ( $linktext === '' ) {
			$linktext = wfMessage( 'translate-edit-jsopen' )->text();
		}
		$output = Html::element( 'a', $a, $linktext );
		return $parser->insertStripItem( $output, $parser->mStripState );
	}
 /**
  * Builds a table with all translations of $title.
  *
  * @param Title $title (default: null)
  */
 function showTranslations(Title $title)
 {
     $handle = new MessageHandle($title);
     $namespace = $title->getNamespace();
     $message = $handle->getKey();
     if (!$handle->isValid()) {
         $this->getOutput()->addWikiMsg('translate-translations-no-message', $title->getPrefixedText());
         return;
     }
     $dbr = wfGetDB(DB_SLAVE);
     $res = $dbr->select('page', array('page_namespace', 'page_title'), array('page_namespace' => $namespace, 'page_title ' . $dbr->buildLike("{$message}/", $dbr->anyString())), __METHOD__, array('ORDER BY' => 'page_title', 'USE INDEX' => 'name_title'));
     if (!$res->numRows()) {
         $this->getOutput()->addWikiMsg('translate-translations-no-message', $title->getPrefixedText());
         return;
     } else {
         $this->getOutput()->addWikiMsg('translate-translations-count', $this->getLanguage()->formatNum($res->numRows()));
     }
     // Normal output.
     $titles = array();
     foreach ($res as $s) {
         $titles[] = $s->page_title;
     }
     $pageInfo = TranslateUtils::getContents($titles, $namespace);
     $tableheader = Xml::openElement('table', array('class' => 'mw-sp-translate-table sortable'));
     $tableheader .= Xml::openElement('tr');
     $tableheader .= Xml::element('th', null, $this->msg('allmessagesname')->text());
     $tableheader .= Xml::element('th', null, $this->msg('allmessagescurrent')->text());
     $tableheader .= Xml::closeElement('tr');
     // Adapted version of TranslateUtils:makeListing() by Nikerabbit.
     $out = $tableheader;
     $canTranslate = $this->getUser()->isAllowed('translate');
     $ajaxPageList = array();
     $historyText = "&#160;<sup>" . $this->msg('translate-translations-history-short')->escaped() . "</sup>&#160;";
     $separator = $this->msg('word-separator')->plain();
     foreach ($res as $s) {
         $key = $s->page_title;
         $tTitle = Title::makeTitle($s->page_namespace, $key);
         $ajaxPageList[] = $tTitle->getPrefixedDBkey();
         $tHandle = new MessageHandle($tTitle);
         $code = $tHandle->getCode();
         $text = TranslateUtils::getLanguageName($code, $this->getLanguage()->getCode());
         $text .= $separator;
         $text .= $this->msg('parentheses')->params($code)->plain();
         $text = htmlspecialchars($text);
         if ($canTranslate) {
             $tools['edit'] = TranslationHelpers::ajaxEditLink($tTitle, $text);
         } else {
             $tools['edit'] = Linker::link($tTitle, $text);
         }
         $tools['history'] = Linker::link($tTitle, $historyText, array('action', 'title' => $this->msg('history-title', $tTitle->getPrefixedDBkey())->text()), array('action' => 'history'));
         if (MessageHandle::hasFuzzyString($pageInfo[$key][0]) || $tHandle->isFuzzy()) {
             $class = 'orig';
         } else {
             $class = 'def';
         }
         $leftColumn = $tools['history'] . $tools['edit'];
         $out .= Xml::tags('tr', array('class' => $class), Xml::tags('td', null, $leftColumn) . Xml::tags('td', array('lang' => $code, 'dir' => Language::factory($code)->getDir()), TranslateUtils::convertWhiteSpaceToHTML($pageInfo[$key][0])));
     }
     $out .= Xml::closeElement('table');
     $this->getOutput()->addHTML($out);
     $vars = array('trlKeys' => $ajaxPageList);
     $this->getOutput()->addScript(Skin::makeVariablesScript($vars));
 }
 public function update(MessageHandle $handle, $targetText)
 {
     if ($handle->getCode() === '') {
         return false;
     }
     /* There are various different cases here:
      * [new or updated] [fuzzy|non-fuzzy] [translation|definition]
      * 1) We don't distinguish between new or updated here.
      * 2) Delete old translation, but not definition
      * 3) Insert new translation or definition, if non-fuzzy
      * The definition should never be fuzzied anyway.
      *
      * These only apply to known messages.
      */
     $update = $this->client->createUpdate();
     $title = $handle->getTitle();
     $doDelete = true;
     $sourceLanguage = '';
     if ($handle->isValid()) {
         $sourceLanguage = $handle->getGroup()->getSourceLanguage();
         if ($handle->getCode() === $sourceLanguage) {
             $doDelete = false;
         }
     }
     if ($doDelete) {
         $base = Title::makeTitle($title->getNamespace(), $handle->getKey());
         $conds = array('wiki' => wfWikiId(), 'language' => $handle->getCode(), 'messageid' => $base->getPrefixedText());
         foreach ($conds as $key => &$value) {
             $value = "{$key}:" . $update->getHelper()->escapePhrase($value);
         }
         $update->addDeleteQuery(implode(' AND ', $conds));
     }
     if ($targetText !== null) {
         if ($handle->isValid()) {
             // Of the message definition page
             $targetTitle = $handle->getTitle();
             $sourceTitle = Title::makeTitle($targetTitle->getNamespace(), $handle->getKey() . '/' . $sourceLanguage);
             $revId = intval($sourceTitle->getLatestRevID());
             /* Note: in some cases the source page might not exist, in this case
              * we use 0 as message version identifier, to differentiate them from
              * orphan messages */
         } else {
             $revId = 'orphan';
         }
         $doc = $this->createDocument($handle, $targetText, $revId);
         // Add document and commit within X seconds.
         $update->addDocument($doc, null, self::COMMIT_WITHIN);
     }
     try {
         $this->client->update($update);
     } catch (Solarium_Exception $e) {
         error_log("SolrTTMServer update-write failed");
         return false;
     }
     return true;
 }
 protected function parseQueryString($queryString, array $opts)
 {
     $fields = $highlights = array();
     $terms = preg_split('/\\s+/', $queryString);
     $match = $opts['match'];
     $case = $opts['case'];
     // Map each word in the query string with its corresponding field
     foreach ($terms as $term) {
         $prefix = strstr($term, '*', true);
         if ($prefix) {
             // For wildcard search
             $fields['content.prefix_complete'][] = $prefix;
         } elseif ($case === '1') {
             // For case sensitive search
             $fields['content.case_sensitive'][] = $term;
         } else {
             $fields['content'][] = $term;
         }
     }
     // Allow searching either by message content or message id (page name
     // without language subpage) with exact match only.
     $searchQuery = new \Elastica\Query\Bool();
     foreach ($fields as $analyzer => $words) {
         foreach ($words as $word) {
             $boolQuery = new \Elastica\Query\Bool();
             $contentQuery = new \Elastica\Query\Match();
             $contentQuery->setFieldQuery($analyzer, $word);
             $boolQuery->addShould($contentQuery);
             $messageQuery = new \Elastica\Query\Term();
             $messageQuery->setTerm('localid', $word);
             $boolQuery->addShould($messageQuery);
             if ($match === 'all') {
                 $searchQuery->addMust($boolQuery);
             } else {
                 $searchQuery->addShould($boolQuery);
             }
             // Fields for highlighting
             $highlights[$analyzer] = array('number_of_fragments' => 0);
             // Allow searching by exact message title (page name with
             // language subpage).
             $title = Title::newFromText($word);
             if (!$title) {
                 continue;
             }
             $handle = new MessageHandle($title);
             if ($handle->isValid() && $handle->getCode() !== '') {
                 $localid = $handle->getTitleForBase()->getPrefixedText();
                 $boolQuery = new \Elastica\Query\Bool();
                 $messageId = new \Elastica\Query\Term();
                 $messageId->setTerm('localid', $localid);
                 $boolQuery->addMust($messageId);
                 $searchQuery->addShould($boolQuery);
             }
         }
     }
     return array($searchQuery, $highlights);
 }