public function execute() { $hours = (int) $this->getOption('days'); $hours = $hours ? $hours * 7 : 7 * 24; $top = (int) $this->getOption('top'); $top = $top ? $top : 10; $bots = $this->hasOption('bots'); $namespaces = array(); if ($this->hasOption('ns')) { $input = explode(',', $this->getOption('ns')); foreach ($input as $namespace) { if (is_numeric($namespace)) { array_push($namespaces, $namespace); } } } /** * Select set of edits to report on */ $rows = TranslateUtils::translationChanges($hours, $bots, $namespaces); /** * Get counts for edits per language code after filtering out edits by FuzzyBot */ $codes = array(); global $wgTranslateFuzzyBotName; foreach ($rows as $_) { // Filter out edits by $wgTranslateFuzzyBotName if ($_->rc_user_text === $wgTranslateFuzzyBotName) { continue; } list(, $code) = TranslateUtils::figureMessage($_->rc_title); if (!isset($codes[$code])) { $codes[$code] = 0; } $codes[$code]++; } /** * Sort counts and report descending up to $top rows. */ arsort($codes); $i = 0; foreach ($codes as $code => $num) { if ($i++ === $top) { break; } $this->output("{$code}\t{$num}\n"); } }
public function execute() { global $wgTranslateFuzzyBotName, $wgSitename; $days = (int) $this->getOption('days', 30); $hours = $days * 24; $top = (int) $this->getOption('top', -1); $bots = $this->hasOption('bots'); $namespaces = array(); if ($this->hasOption('ns')) { $input = explode(',', $this->getOption('ns')); foreach ($input as $namespace) { if (is_numeric($namespace)) { $namespaces[] = $namespace; } } } // Select set of edits to report on // Fetch some extrac fields that normally TranslateUtils::translationChanges wont $extraFields = array('rc_old_len', 'rc_new_len'); $rows = TranslateUtils::translationChanges($hours, $bots, $namespaces, $extraFields); // Get counts for edits per language code after filtering out edits by FuzzyBot $codes = array(); foreach ($rows as $_) { // Filter out edits by $wgTranslateFuzzyBotName if ($_->rc_user_text === $wgTranslateFuzzyBotName) { continue; } $handle = new MessageHandle(Title::newFromText($_->rc_title)); $code = $handle->getCode(); if (!isset($codes[$code])) { $codes[$code] = 0; } if ($this->hasOption('diff')) { $diff = abs($_->rc_new_len - $_->rc_old_len); } else { $diff = $_->rc_new_len; } $codes[$code] += $diff; } // Sort counts and report descending up to $top rows. arsort($codes); $i = 0; $total = 0; $this->output("Character edit stats for last {$days} days in {$wgSitename}\n"); $this->output("code\tname\tedit\n"); $this->output("-----------------------\n"); foreach ($codes as $code => $num) { if ($i++ === $top) { break; } $language = Language::fetchLanguageName($code); if (!$language) { // this will be very rare, but avoid division by zero in next line continue; } $charRatio = mb_strlen($language, 'UTF-8') / strlen($language); $num = intval($num * $charRatio); $total += $num; $this->output("{$code}\t{$language}\t{$num}\n"); } $this->output("-----------------------\n"); $this->output("Total\t\t{$total}\n"); }
public function execute() { $target = $this->getOption('target'); if (!is_writable($target)) { $this->error("Target directory is not writable ({$target}).", 1); } $threshold = $this->getOption('threshold'); $noFuzzy = $this->hasOption('no-fuzzy'); $noLocation = ''; if ($this->hasOption('no-location')) { $noLocation = '--no-location '; } $skip = array(); if ($this->hasOption('skip')) { $skip = array_map('trim', explode(',', $this->getOption('skip'))); } $reqLangs = TranslateUtils::parseLanguageCodes($this->getOption('lang')); $reqLangs = array_flip($reqLangs); foreach ($skip as $skipLang) { unset($reqLangs[$skipLang]); } $reqLangs = array_flip($reqLangs); $codemapOnly = $this->hasOption('codemaponly'); $groupIds = explode(',', trim($this->getOption('group'))); $groupIds = MessageGroups::expandWildcards($groupIds); $groups = MessageGroups::getGroupsById($groupIds); /** @var FileBasedMessageGroup $group */ foreach ($groups as $groupId => $group) { if ($group->isMeta()) { $this->output("Skipping meta message group {$groupId}.\n"); unset($groups[$groupId]); continue; } if (!$group instanceof FileBasedMessageGroup) { $this->output("EE2: Unexportable message group {$groupId}.\n"); unset($groups[$groupId]); continue; } } if (!count($groups)) { $this->error("EE1: No valid message groups identified.", 1); } $changeFilter = false; $hours = $this->getOption('hours'); if ($hours) { $namespaces = array(); /** @var FileBasedMessageGroup $group */ foreach ($groups as $group) { $namespaces[$group->getNamespace()] = true; } $namespaces = array_keys($namespaces); $bots = true; $changeFilter = array(); $rows = TranslateUtils::translationChanges($hours, $bots, $namespaces); foreach ($rows as $row) { $title = Title::makeTitle($row->rc_namespace, $row->rc_title); $handle = new MessageHandle($title); $code = $handle->getCode(); if (!$code) { continue; } $groupIds = $handle->getGroupIds(); foreach ($groupIds as $groupId) { $changeFilter[$groupId][$code] = true; } } } $skipGroups = array(); if ($this->hasOption('skipgroup')) { $skipGroups = array_map('trim', explode(',', $this->getOption('skipgroup'))); } foreach ($groups as $groupId => $group) { if (in_array($groupId, $skipGroups)) { $this->output("Group {$groupId} is in skipgroup.\n"); continue; } // No changes to this group at all if (is_array($changeFilter) && !isset($changeFilter[$groupId])) { $this->output("No recent changes to {$groupId}.\n"); continue; } $langs = $reqLangs; if ($codemapOnly) { foreach ($langs as $index => $code) { if ($group->mapCode($code) === $code) { unset($langs[$index]); } } } if ($threshold) { $stats = MessageGroupStats::forGroup($groupId); foreach ($langs as $index => $code) { if (!isset($stats[$code])) { unset($langs[$index]); continue; } $total = $stats[$code][MessageGroupStats::TOTAL]; $translated = $stats[$code][MessageGroupStats::TRANSLATED]; if ($translated / $total * 100 < $threshold) { unset($langs[$index]); } } } // Filter out unchanged languages from requested languages if (is_array($changeFilter)) { $langs = array_intersect($langs, array_keys($changeFilter[$groupId])); } if (!count($langs)) { continue; } $this->output("Exporting {$groupId}...\n"); $ffs = $group->getFFS(); $ffs->setWritePath($target); $sourceLanguage = $group->getSourceLanguage(); $collection = $group->initCollection($sourceLanguage); $definitionFile = false; if ($this->hasOption('ppgettext') && $ffs instanceof GettextFFS) { global $wgMaxShellMemory, $wgTranslateGroupRoot; // Need more shell memory for msgmerge. $wgMaxShellMemory = 402400; $path = $group->getSourceFilePath($sourceLanguage); $definitionFile = str_replace($wgTranslateGroupRoot, $this->getOption('ppgettext'), $path); } $whitelist = $group->getTranslatableLanguages(); foreach ($langs as $lang) { // Do not export languges that are blacklisted (or not whitelisted). // Also check that whitelist is not null, which means that all // languages are allowed for translation and export. if (is_array($whitelist) && !isset($whitelist[$lang])) { continue; } $collection->resetForNewLanguage($lang); $collection->loadTranslations(); // Don't export ignored, unless it is the source language // or message documentation global $wgTranslateDocumentationLanguageCode; if ($lang !== $wgTranslateDocumentationLanguageCode && $lang !== $sourceLanguage) { $collection->filter('ignored'); } if ($noFuzzy) { $collection->filter('fuzzy'); } $ffs->write($collection); // Do post processing if requested. if ($definitionFile) { if (is_file($definitionFile)) { $targetFileName = $ffs->getWritePath() . "/" . $group->getTargetFilename($collection->code); $cmd = "msgmerge --quiet " . $noLocation . "--output-file=" . $targetFileName . ' ' . $targetFileName . ' ' . $definitionFile; wfShellExec($cmd, $ret); // Report on errors. if ($ret) { $this->error("ERROR: {$ret}"); } } else { $this->error("{$definitionFile} does not exist.", 1); } } } } }
$skip = array(); } if ( isset( $options['groups'] ) ) { $groupsFilter = array_map( 'trim', explode( ',', $options['groups'] ) ); } else { $groupsFilter = array(); } if ( isset( $options['threshold'] ) && intval( $options['threshold'] ) ) { $threshold = $options['threshold']; } else { $threshold = false; } $rows = TranslateUtils::translationChanges( $hours, true ); $exports = array(); foreach ( $rows as $row ) { $group = false; $code = false; // @todo Fixme list( $pieces, ) = explode( '/', $wgContLang->lcfirst( $row->rc_title ), 2 ); $mg = TranslateUtils::messageKeyToGroup( $row->rc_namespace, $pieces ); if ( !is_null( $mg ) ) { $group = $mg; } if ( strpos( $row->rc_title, '/' ) !== false ) {
} } } function figureMessage( $text ) { $pos = strrpos( $text, '/' ); $code = substr( $text, $pos + 1 ); $key = substr( $text, 0, $pos ); return array( $key, $code ); } /** * Select set of edits to report on */ $rows = TranslateUtils::translationChanges( $hours, $bots, $namespaces ); /** * Get counts for edits per language code after filtering out edits by FuzzyBot */ $codes = array(); foreach ( $rows as $_ ) { // Filter out edits by $wgTranslateFuzzyBotName if ( $_->rc_user_text === $wgTranslateFuzzyBotName ) { continue; } list( , $code ) = figureMessage( $_->rc_title ); if ( !isset( $codes[$code] ) ) { $codes[$code] = 0;