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; }
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); } } } } }
/** * Returns the message groups this message group is part of. * @since 2011-12-25 * @return array */ public static function getParentGroups(MessageGroup $group) { // Take the first message, get a handle for it and check // if that message belongs to other groups. Those are the // parent aggregate groups. Ideally we loop over all keys, // but this should be enough. $keys = array_keys($group->getDefinitions()); $title = Title::makeTitle($group->getNamespace(), $keys[0]); $handle = new MessageHandle($title); $ids = $handle->getGroupIds(); foreach ($ids as $index => $id) { if ($id === $group->getId()) { unset($ids[$index]); } } return $ids; }
/** * Prevent editing of restricted languages. * Hook: getUserPermissionsErrorsExpensive * @since 2012-03-01 */ public static function preventRestrictedTranslations(Title $title, User $user, $action, &$result) { global $wgTranslateDocumentationLanguageCode; // Preventing editing (includes creation) should be enough if ($action !== 'edit') { return true; } $handle = new MessageHandle($title); if (!$handle->isValid()) { return true; } // Get the primary group id $ids = $handle->getGroupIds(); $groupId = $ids[0]; // Check if anything is prevented for the group in the first place $force = TranslateMetadata::get($groupId, 'priorityforce'); if ($force !== 'on') { return true; } // Allow adding message documentation even when translation is restricted if ($handle->getCode() === $wgTranslateDocumentationLanguageCode) { return true; } // And finally check whether the language is not included in whitelist $languages = TranslateMetadata::get($groupId, 'prioritylangs'); $filter = array_flip(explode(',', $languages)); if (!isset($filter[$handle->getCode()])) { // @todo Default reason if none provided $reason = TranslateMetadata::get($groupId, 'priorityreason'); $result = array('tpt-translation-restricted', $reason); return false; } return true; }
public static function update( MessageHandle $handle, $changes = array() ) { $dbw = wfGetDB( DB_MASTER ); $conds = array( 'tgs_group' => $handle->getGroupIds(), 'tgs_lang' => $handle->getCode(), ); $values = array(); foreach ( array( 'total', 'translated', 'fuzzy' ) as $type ) { if ( !isset( $changes[$type] ) ) { $values[] = "tgs_$type=tgs_$type" . self::stringifyNumber( $changes[$type] ); } } $dbw->update( self::TABLE, $values, $conds, __METHOD__ ); }
/** * @see schema.xml */ protected function createDocument(MessageHandle $handle, $text, $revId) { $language = $handle->getCode(); $translationTitle = $handle->getTitle(); $title = Title::makeTitle($handle->getTitle()->getNamespace(), $handle->getKey()); $wiki = wfWikiId(); $messageid = $title->getPrefixedText(); $globalid = "{$wiki}-{$messageid}-{$revId}/{$language}"; $doc = new Solarium_Document_ReadWrite(); $doc->wiki = $wiki; $doc->uri = $translationTitle->getCanonicalUrl(); $doc->messageid = $messageid; $doc->globalid = $globalid; $doc->language = $language; $doc->content = $text; $doc->setField('group', $handle->getGroupIds()); return $doc; }
/** * @return \Elastica\Document */ protected function createDocument(MessageHandle $handle, $text, $revId) { $language = $handle->getCode(); $localid = $handle->getTitleForBase()->getPrefixedText(); $wiki = wfWikiId(); $globalid = "{$wiki}-{$localid}-{$revId}/{$language}"; $data = array('wiki' => $wiki, 'uri' => $handle->getTitle()->getCanonicalUrl(), 'localid' => $localid, 'language' => $language, 'content' => $text, 'group' => $handle->getGroupIds()); return new \Elastica\Document($globalid, $data); }