public function execute() { $user = $this->getUser(); $requestParams = $this->extractRequestParams(); $group = MessageGroups::getGroup($requestParams['group']); $code = $requestParams['language']; if (!$group || MessageGroups::isDynamic($group)) { $this->dieUsageMsg(array('missingparam', 'group')); } $stateConfig = $group->getMessageGroupStates()->getStates(); if (!$stateConfig) { $this->dieUsage('Message group review not in use', 'disabled'); } if (!$user->isAllowed(self::$right)) { $this->dieUsage('Permission denied', 'permissiondenied'); } if ($user->isBlocked()) { $this->dieUsage('You have been blocked', 'blocked'); } $requestParams = $this->extractRequestParams(); $languages = Language::fetchLanguageNames(); if (!isset($languages[$code])) { $this->dieUsageMsg(array('missingparam', 'language')); } $targetState = $requestParams['state']; if (!isset($stateConfig[$targetState])) { $this->dieUsage('The requested state is invalid', 'invalidstate'); } if (is_array($stateConfig[$targetState]) && isset($stateConfig[$targetState]['right']) && !$user->isAllowed($stateConfig[$targetState]['right'])) { $this->dieUsage('Permission denied', 'permissiondenied'); } self::changeState($group, $code, $targetState, $user); $output = array('review' => array('group' => $group->getId(), 'language' => $code, 'state' => $targetState)); $this->getResult()->addValue(null, $this->getModuleName(), $output); }
public function rebuild($scratch = false) { $groups = MessageGroups::singleton()->getGroups(); $new = $old = array(); if (!$scratch) { // To avoid inifinite recursion $old = $this->retrieve(); } $postponed = array(); STDOUT("Working with ", 'main'); foreach ($groups as $g) { if (!$g->exists()) { continue; } # Skip meta thingies if ($g->isMeta()) { $postponed[] = $g; continue; } $this->checkAndAdd($new, $g); } foreach ($postponed as $g) { $this->checkAndAdd($new, $g, true); } $this->store($new); $this->clearMessageGroupStats($old, $new); return $new; }
/** * Group is either MessageGroup object or group id. * @param $group MessagerGroup|string */ public function setGroup( $group ) { if ( $group instanceof MessageGroup ) { $this->group = $group; } else { $this->group = MessageGroups::getGroup( $group ); } }
private function displayNavigation() { global $wgOut; $groupSelector = new XmlSelect('group', 'group-select'); // pull groups $groups = MessageGroups::singleton()->getGroups(); foreach ($groups as $group) { if (!$group->isMeta()) { continue; } $groupSelector->addOption($group->getLabel(), $group->getId()); } $fields = array(); $fields['transstats-choose-group'] = $groupSelector->getHTML(); $fields['transstats-group-mode-all'] = Xml::radio('mode', 0, empty($this->mMode)); $fields['transstats-group-mode-supress0'] = Xml::radio('mode', 1, $this->mMode == 1); $fields['transstats-group-mode-supress100'] = Xml::radio('mode', 2, $this->mMode == 2); $fields['transstats-group-mode-only100'] = Xml::radio('mode', 3, $this->mMode == 3); $fields['transstats-group-langlist'] = Xml::input('langlist', false, $this->mLanglistPlain); $out = Xml::openElement('form'); $out .= Xml::buildForm($fields); $out .= Html::hidden('title', 'Special:' . $this->getName()); // FIXME: this is silly... $out .= Xml::submitButton(wfMsg('transstats-submit')); $out .= Xml::closeElement('form'); $wgOut->addHTML($out); }
public function testAPIFilterAccuracy() { $ids = array('MadeUpGroup'); $ids += array_keys(MessageGroups::getAllGroups()); foreach ($ids as $id) { list($data) = $this->doApiRequest(array('action' => 'query', 'meta' => 'messagegroups', 'mgprop' => 'id|label|class|namespace|exists', 'mgfilter' => $id, 'continue' => '')); if ($id === 'MadeUpGroup') { // Check structure (shouldn't find anything) $this->assertArrayNotHasKey('warnings', $data); $this->assertArrayHasKey('query', $data); $this->assertCount(1, $data['query']); $this->assertArrayHasKey('messagegroups', $data['query']); $this->assertCount(0, $data['query']['messagegroups']); continue; } // Check structure (filter is unique given these names) $this->assertArrayNotHasKey('warnings', $data); $this->assertArrayHasKey('query', $data); $this->assertCount(1, $data['query']); $this->assertArrayHasKey('messagegroups', $data['query']); $this->assertCount(1, $data['query']['messagegroups']); // Check content $item = $data['query']['messagegroups'][0]; $this->assertCount(5, $item); $this->assertSame($item['id'], $id); $this->assertSame($item['label'], 'thelabel'); $this->assertSame($item['exists'], true); $this->assertStringEndsWith('id', $item['id']); // theid, anotherid $this->assertSame($item['namespace'], 5); $this->assertSame($item['class'], 'WikiMessageGroup'); } }
public function testMessage() { $user = new MockSuperUser(); $user->setId(123); $title = Title::newFromText('MediaWiki:translated/fi'); $page = WikiPage::factory($title); $content = ContentHandler::makeContent('pupuliini', $title); $status = $page->doEditContent($content, __METHOD__, 0, false, $user); $value = $status->getValue(); $rev = $value['revision']; $revision = $rev->getId(); $group = MessageGroups::getGroup('test-group'); $collection = $group->initCollection('fi'); $collection->loadTranslations(); /** @var TMessage $translated */ $translated = $collection['translated']; $this->assertInstanceof('TMessage', $translated); $this->assertEquals('translated', $translated->key()); $this->assertEquals('bunny', $translated->definition()); $this->assertEquals('pupuliini', $translated->translation()); $this->assertEquals('SuperUser', $translated->getProperty('last-translator-text')); $this->assertEquals(123, $translated->getProperty('last-translator-id')); $this->assertEquals('translated', $translated->getProperty('status'), 'message status is translated'); $this->assertEquals($revision, $translated->getProperty('revision')); /** @var TMessage $untranslated */ $untranslated = $collection['untranslated']; $this->assertInstanceof('TMessage', $untranslated); $this->assertEquals(null, $untranslated->translation(), 'no translation is null'); $this->assertEquals(false, $untranslated->getProperty('last-translator-text')); $this->assertEquals(false, $untranslated->getProperty('last-translator-id')); $this->assertEquals('untranslated', $untranslated->getProperty('status'), 'message status is untranslated'); $this->assertEquals(false, $untranslated->getProperty('revision')); }
/** * Itterate through all groups, loading current data from the existing * extension and opening message files for message output. * - If the group does not define a special page alias file or magic * words file, or that file does not exist, it is ignored silently. * - If the file does contain a data array (e.g. $aliases) then the * program exits. */ protected function openHandles() { $this->output( "Opening file handles and loading current data...\n" ); $groups = MessageGroups::singleton()->getGroups(); $filename = null; foreach ( $groups as $group ) { if ( !$group instanceof ExtensionMessageGroup ) { continue; } switch ( $this->type ) { case 'special': $filename = $group->getAliasFile(); break; case 'magic': $filename = $group->getMagicFile(); break; } if ( $filename === null ) { continue; } global $wgTranslateExtensionDirectory; $inFile = "$wgTranslateExtensionDirectory/$filename"; if ( !file_exists( $inFile ) ) { continue; } include( $inFile ); switch( $this->type ) { case 'special': if ( isset( $aliases ) ) { $this->messagesOld[$group->getId()] = $aliases; unset( $aliases ); } elseif ( isset( $specialPageAliases ) ) { $this->messagesOld[$group->getId()] = $specialPageAliases; unset( $specialPageAliases ); } else { die( "File '$inFile' does not contain an aliases array.\n" ); } break; case 'magic': if ( !isset( $magicWords ) ) { die( "File '$inFile' does not contain a magic words array.\n" ); } $this->messagesOld[$group->getId()] = $magicWords; unset( $magicWords ); break; } $outFile = $this->target . '/' . $filename; wfMkdirParents( dirname( $outFile ), null, __METHOD__ ); $this->handles[$group->getId()] = fopen( $outFile, 'w' ); fwrite( $this->handles[$group->getId()], $this->readHeader( $inFile ) ); $this->output( "\t{$group->getId()}\n" ); } }
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); }
/** * Returns translated percentage for message group in given * languages * * @param $group \string Unique key identifying the group * @param $languages \array List of language codes * @param $threshold \int Minimum required percentage translated to * return. Other given language codes will not be returned. * @param $simple \bool Return only codes or code/pecentage pairs * * @return \array Array of key value pairs code (string)/percentage * (float) or array of codes, depending on $simple */ public static function getPercentageTranslated( $group, $languages, $threshold = false, $simple = false ) { $stats = array(); $g = MessageGroups::singleton()->getGroup( $group ); $collection = $g->initCollection( 'en' ); foreach ( $languages as $code ) { $collection->resetForNewLanguage( $code ); // Initialise messages $collection->filter( 'ignored' ); $collection->filter( 'optional' ); // Store the count of real messages for later calculation. $total = count( $collection ); $collection->filter( 'translated', false ); $translated = count( $collection ); $translatedPercentage = ( $translated * 100 ) / $total; if ( $translatedPercentage >= $threshold ) { if ( $simple ) { $stats[] = $code; } else { $stats[$code] = $translatedPercentage; } } } return $stats; }
/** * Special page entry point. */ public function execute( $parameters ) { $this->setHeaders(); // Security and validity checks if ( !$this->userCanExecute( $this->user ) ) { $this->displayRestrictionError(); return; } if ( !$this->request->wasPosted() ) { $this->outputForm(); return; } if ( !$this->user->matchEditToken( $this->request->getVal( 'token' ) ) ) { $this->out->addWikiMsg( 'session_fail_preview' ); $this->outputForm(); return; } if ( $this->request->getCheck( 'process' ) ) { $data = $this->getCachedData(); if ( !$data ) { $this->out->addWikiMsg( 'session_fail_preview' ); $this->outputForm(); return; } } else { /** * Proceed to loading and parsing if possible * @todo: use a Status object instead? */ $file = null; $msg = $this->loadFile( $file ); if ( $this->checkError( $msg ) ) return; $msg = $this->parseFile( $file ); if ( $this->checkError( $msg ) ) return; $data = $msg[1]; $this->setCachedData( $data ); } $messages = $data['MESSAGES']; $group = $data['METADATA']['group']; $code = $data['METADATA']['code']; if ( !MessageGroups::exists( $group ) ) { $errorWrap = "<div class='error'>\n$1\n</div>"; $this->out->wrapWikiMsg( $errorWrap, 'translate-import-err-stale-group' ); return; } $importer = new MessageWebImporter( $this->getTitle(), $group, $code ); $alldone = $importer->execute( $messages ); if ( $alldone ) { $this->deleteCachedData(); } }
public function execute() { $groupIds = explode(',', trim($this->getOption('group'))); $groupIds = MessageGroups::expandWildcards($groupIds); $groups = MessageGroups::getGroupsById($groupIds); if (!count($groups)) { $this->error("ESG2: No valid message groups identified.", 1); } $start = $this->getOption('start') ? strtotime($this->getOption('start')) : false; $end = $this->getOption('end') ? strtotime($this->getOption('end')) : false; $this->output("Conflict times: " . wfTimestamp(TS_ISO_8601, $start) . " - " . wfTimestamp(TS_ISO_8601, $end) . "\n"); $codes = array_filter(array_map('trim', explode(',', $this->getOption('lang')))); $supportedCodes = array_keys(TranslateUtils::getLanguageNames('en')); ksort($supportedCodes); if ($codes[0] === '*') { $codes = $supportedCodes; } /** @var FileBasedMessageGroup $group */ foreach ($groups as $groupId => &$group) { if ($group->isMeta()) { $this->output("Skipping meta message group {$groupId}.\n"); continue; } $this->output("{$group->getLabel()} ", $group); foreach ($codes as $code) { // No sync possible for unsupported language codes. if (!in_array($code, $supportedCodes)) { $this->output("Unsupported code " . $code . ": skipping.\n"); continue; } $file = $group->getSourceFilePath($code); if (!$file) { continue; } if (!file_exists($file)) { continue; } $cs = new ChangeSyncer($group, $this); $cs->setProgressCallback(array($this, 'myOutput')); $cs->interactive = !$this->hasOption('noask'); $cs->nocolor = $this->hasOption('nocolor'); $cs->norc = $this->hasOption('norc'); # @todo FIXME: Make this auto detect. # Guess last modified date of the file from either git, svn or filesystem if ($this->hasOption('git')) { $ts = $cs->getTimestampsFromGit($file); } else { $ts = $cs->getTimestampsFromSvn($file); } if (!$ts) { $ts = $cs->getTimestampsFromFs($file); } $this->output("Modify time for {$code}: " . wfTimestamp(TS_ISO_8601, $ts) . "\n"); $cs->checkConflicts($code, $start, $end, $ts); } unset($group); } // Print timestamp if the user wants to store it $this->output(wfTimestamp(TS_RFC2822) . "\n"); }
public function getDefinitions() { $groups = MessageGroups::getAllGroups(); $keys = array(); /** * @var $g MessageGroup */ foreach ($groups as $g) { $states = $g->getMessageGroupStates()->getStates(); foreach (array_keys($states) as $state) { $keys["Translate-workflow-state-{$state}"] = $state; } } $defs = TranslateUtils::getContents(array_keys($keys), $this->getNamespace()); foreach ($keys as $key => $state) { if (!isset($defs[$key])) { // @todo Use jobqueue $title = Title::makeTitleSafe($this->getNamespace(), $key); $page = new WikiPage($title); $content = ContentHandler::makeContent($state, $title); $page->doEditContent($content, wfMessage('translate-workflow-autocreated-summary', $state)->inContentLanguage()->text(), 0, false, FuzzyBot::getUser()); } else { // Use the wiki translation as definition if available. // getContents returns array( content, last author ) list($content, ) = $defs[$key]; $keys[$key] = $content; } } return $keys; }
/** * Contructs a new cache object for given group and language code. * @param $group \types{String,FileBasedMessageGroup} Group object or id. * @param $code \string Language code. Default value 'en'. */ public function __construct( $group, $code = 'en' ) { if ( is_object( $group ) ) { $this->group = $group; } else { $this->group = MessageGroups::getGroup( $group ); } $this->code = $code; }
protected function isValidValue($value) { $group = MessageGroups::getGroup($value); if ($group) { $this->target = $group->getId(); } return (bool) $group; }
public function execute() { $server = TTMServer::primary(); if ($server instanceof FakeTTMServer) { $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); $this->statusLine('Loading groups... ', 2); $groups = MessageGroups::singleton()->getGroups(); $this->output('done!', 2); $threads = $this->getOption('threads', 1); $pids = array(); foreach ($groups as $id => $group) { if ($group->isMeta()) { continue; } // Fork to avoid unbounded memory usage growth $pid = pcntl_fork(); if ($pid === 0) { // Child, reseed because there is no bug in PHP: // http://bugs.php.net/bug.php?id=42465 mt_srand(getmypid()); $this->exportGroup($group, $threads > 1); exit; } elseif ($pid === -1) { // Fork failed do it serialized $this->exportGroup($group); } else { $this->statusLine("Forked thread {$pid} to handle {$id}\n"); $pids[$pid] = true; // If we hit the thread limit, wait for any child to finish. if (count($pids) >= $threads) { $status = 0; $pid = pcntl_wait($status); unset($pids[$pid]); } } } // Return control after all threads have finished. foreach (array_keys($pids) as $pid) { $status = 0; 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); }
public function testHaveSingleSourceLanguage() { $this->setMwGlobals(array('wgTranslateGroupFiles' => array(__DIR__ . '/data/MixedSourceLanguageGroups.yaml'))); MessageGroups::singleton()->recache(); $enGroup1 = MessageGroups::getGroup('EnglishGroup1'); $enGroup2 = MessageGroups::getGroup('EnglishGroup2'); $teGroup1 = MessageGroups::getGroup('TeluguGroup1'); $this->assertEquals('en', MessageGroups::haveSingleSourceLanguage(array($enGroup1, $enGroup2))); $this->assertEquals('', MessageGroups::haveSingleSourceLanguage(array($enGroup1, $enGroup2, $teGroup1))); }
/** * Tries to determine to which group this message belongs. It tries to get * group id from loadgroup GET-paramater, but fallbacks to messageIndex file * if no valid group was provided. * * @return MessageGroup which the key belongs to, or null. */ protected function getMessageGroup(MessageHandle $handle, $groupId) { $mg = MessageGroups::getGroup($groupId); # If we were not given (a valid) group if ($mg === null) { $groupId = MessageIndex::getPrimaryGroupId($handle); $mg = MessageGroups::getGroup($groupId); } return $mg; }
protected function getData() { $params = $this->extractRequestParams(); $group = MessageGroups::getGroup($params['group']); if (!$group) { $this->dieUsageMsg(array('missingparam', 'mcgroup')); } elseif (MessageGroups::isDynamic($group)) { $this->dieUsage('Dynamic message groups are not supported here', 'invalidparam'); } return MessageGroupStats::forGroup($group->getId()); }
protected function setUp() { parent::setUp(); global $wgHooks; $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgGroupPermissions' => array(), 'wgTranslateMessageNamespaces' => array(NS_MEDIAWIKI))); $wgHooks['TranslatePostInitGroups'] = array(array($this, 'getTestGroups')); $mg = MessageGroups::singleton(); $mg->setCache(wfGetCache('hash')); $mg->recache(); MessageIndex::setInstance(new HashMessageIndex()); MessageIndex::singleton()->rebuild(); }
protected function setUp() { parent::setUp(); global $wgHooks; $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array(), 'wgTranslateCacheDirectory' => $this->getNewTempDirectory())); $wgHooks['TranslatePostInitGroups'] = array(); $mg = MessageGroups::singleton(); $mg->setCache(wfGetCache('hash')); $mg->recache(); MessageIndex::setInstance(new HashMessageIndex()); MessageIndex::singleton()->rebuild(); }
public function setUp() { parent::setUp(); global $wgHooks; $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array(), 'wgTranslateDelayedMessageIndexRebuild' => false)); $wgHooks['TranslatePostInitGroups'] = array(); $mg = MessageGroups::singleton(); $mg->setCache(wfGetCache('hash')); $mg->recache(); MessageIndex::setInstance(new HashMessageIndex()); MessageIndex::singleton()->rebuild(); }
/** * Iterate through all groups, loading current data from the existing * extension and opening message files for message output. * - If the group does not define a special page alias file or magic * words file, or that file does not exist, it is ignored silently. * - If the file does contain a data array (e.g. $aliases) then the * program exits. */ protected function openHandles() { $this->output("Opening file handles and loading current data...\n"); $groups = MessageGroups::singleton()->getGroups(); foreach ($groups as $group) { if (!$group instanceof MediaWikiExtensionMessageGroup) { continue; } $conf = $group->getConfiguration(); $inFile = $outFile = null; if ($this->type === 'special' && isset($conf['FILES']['aliasFile'])) { $inFile = $conf['FILES']['aliasFileSource']; $outFile = $conf['FILES']['aliasFile']; } if ($this->type === 'magic' && isset($conf['FILES']['magicFile'])) { $inFile = $conf['FILES']['magicFileSource']; $outFile = $conf['FILES']['magicFile']; } if ($inFile === null) { continue; } $inFile = $group->replaceVariables($inFile, 'en'); $outFile = $this->target . '/' . $outFile; include $inFile; switch ($this->type) { case 'special': if (isset($aliases)) { $this->messagesOld[$group->getId()] = $aliases; unset($aliases); } elseif (isset($specialPageAliases)) { $this->messagesOld[$group->getId()] = $specialPageAliases; unset($specialPageAliases); } else { $this->error("File '{$inFile}' does not contain an aliases array."); continue; } break; case 'magic': if (!isset($magicWords)) { $this->error("File '{$inFile}' does not contain a magic words array."); continue; } $this->messagesOld[$group->getId()] = $magicWords; unset($magicWords); break; } wfMkdirParents(dirname($outFile), null, __METHOD__); $this->handles[$group->getId()] = fopen($outFile, 'w'); fwrite($this->handles[$group->getId()], $this->readHeader($inFile)); $this->output("\t{$group->getId()}\n"); } }
public static function populateStats() { // remove all records $dbw = wfGetDB(DB_MASTER); $dbw->delete('groupstats', '*'); $groups = MessageGroups::singleton()->getGroups(); // iterate over all groups foreach ($groups as $g) { /* @var $g MessageGroup */ echo "Populating " . $g->getId() . "...\n"; self::forGroup($g->getId()); } echo "Done!\n"; }
public function execute() { $this->files = array(); $groups = MessageGroups::singleton()->getGroups(); $target = $this->getOption( 'path' ); foreach ( $groups as $group ) { if ( !$group instanceof ExtensionMessageGroup ) continue; if ( $target && $group->getPath() !== $target ) continue; $this->addPaths( $group->getMessageFile( 'en' ) ); $this->addPaths( $group->getAliasFile( 'en' ) ); $this->addPaths( $group->getMagicFile( 'en' ) ); } $files = array_keys( $this->files ); $this->output( trim( implode( "\n", $files ) . "\n" ) ); }
public static function getGroupsWithTransitions(MessageHandle $handle) { $listeners = array(); foreach ($handle->getGroupIds() as $id) { $group = MessageGroups::getGroup($id); // No longer exists? if (!$group) { continue; } $conds = $group->getMessageGroupStates()->getConditions(); if ($conds) { $listeners[$id] = $conds; } } return $listeners; }
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()); }
public function execute() { $groups = MessageGroups::singleton()->getGroups(); /** @var MessageGroup $group */ foreach ($groups as $group) { if (!$group instanceof WikiPageMessageGroup) { continue; } // Get all translation subpages and refresh each one of them $page = TranslatablePage::newFromTitle($group->getTitle()); $translationPages = $page->getTranslationPages(); foreach ($translationPages as $subpage) { $job = TranslateRenderJob::newJob($subpage); $job->run(); } } }
public function testTranslationPageRestrictions() { $superUser = new MockSuperUser(); $title = Title::newFromText('Translatable page'); $page = WikiPage::factory($title); $content = ContentHandler::makeContent('<translate>Hello</translate>', $title); $status = $page->doEditContent($content, 'New page', 0, false, $superUser); $revision = $status->value['revision']->getId(); $translatablePage = TranslatablePage::newFromRevision($title, $revision); $translatablePage->addMarkedTag($revision); MessageGroups::singleton()->recache(); $translationPage = Title::newFromText('Translatable page/fi'); TranslateRenderJob::newJob($translationPage)->run(); $this->assertTrue($translationPage->userCan('read', $superUser), 'Users can read existing translation pages'); $this->assertFalse($translationPage->userCan('edit', $superUser), 'Users can not edit existing translation pages'); $translationPage = Title::newFromText('Translatable page/ab'); $this->assertTrue($translationPage->userCan('read', $superUser), 'Users can read non-existing translation pages'); $this->assertFalse($translationPage->userCan('edit', $superUser), 'Users can not edit non-existing translation pages'); }
/** * @group Broken * This tests fails regularly on WMF CI but haven't been able to reproduce locally. */ public function testHooks() { $user = new MockSuperUser(); $group = MessageGroups::getGroup('group-trans'); // In the beginning... $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals(false, $currentState, 'groups start from unset state'); // First translation $title = Title::newFromText('MediaWiki:key1/fi'); $page = WikiPage::factory($title); $content = ContentHandler::makeContent('trans1', $title); $status = $page->doEditContent($content, __METHOD__, 0, false, $user); self::runJobs(); $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals('inprogress', $currentState, 'in progress after first translation'); // First review ApiTranslationReview::doReview($user, self::getRevision($status), __METHOD__); self::runJobs(); $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals('inprogress', $currentState, 'in progress while untranslated messages'); // Second translation $title = Title::newFromText('MediaWiki:key2/fi'); $page = WikiPage::factory($title); $content = ContentHandler::makeContent('trans2', $title); $status = $page->doEditContent($content, __METHOD__, 0, false, $user); self::runJobs(); $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals('proofreading', $currentState, 'proofreading after second translation'); // Second review ApiTranslationReview::doReview($user, self::getRevision($status), __METHOD__); self::runJobs(); $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals('ready', $currentState, 'ready when all proofread'); // Change to translation $title = Title::newFromText('MediaWiki:key1/fi'); $page = WikiPage::factory($title); $content = ContentHandler::makeContent('trans1 updated', $title); $page->doEditContent($content, __METHOD__, 0, false, $user); self::runJobs(); $currentState = ApiGroupReview::getState($group, 'fi'); $this->assertEquals('proofreading', $currentState, 'back to proofreading after translation changed'); }
public function execute() { $groups = MessageGroups::getAllGroups(); $result = $this->getResult(); foreach ($groups as $id => $g) { $a = array(); $a['id'] = $id; $a['label'] = $g->getLabel(); $a['description'] = $g->getDescription(); $a['class'] = get_class($g); $a['exists'] = $g->exists(); // TODO: Add a continue? $fit = $result->addValue(array('query', $this->getModuleName()), null, $a); if (!$fit) { // Even if we're not going to give a continue, no point carrying on if the result is full break; } } $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'group'); }