protected function loadMessagesFromCache($groups)
 {
     $messages = array();
     foreach ($groups as $group) {
         if ($group instanceof MessageGroupOld) {
             $messages += $group->getDefinitions();
             continue;
         }
         if ($group instanceof AggregateMessageGroup) {
             $messages += $this->loadMessagesFromCache($group->getGroups());
             continue;
         }
         $cache = new MessageGroupCache($group);
         if ($cache->exists()) {
             foreach ($cache->getKeys() as $key) {
                 $messages[$key] = $cache->get($key);
             }
         }
     }
     return $messages;
 }
Example #2
0
 /**
  * @param $hugearray array
  * @param $g
  * @param $ignore bool
  */
 protected function checkAndAdd(&$hugearray, $g, $ignore = false)
 {
     if ($g instanceof MessageGroupBase) {
         $cache = new MessageGroupCache($g);
         if ($cache->exists()) {
             $keys = $cache->getKeys();
         } else {
             $keys = array_keys($g->getDefinitions());
         }
     } else {
         $messages = $g->getDefinitions();
         if (!is_array($messages)) {
             return;
         }
         $keys = array_keys($messages);
     }
     $id = $g->getId();
     STDOUT("{$id} ", 'main');
     $namespace = $g->getNamespace();
     foreach ($keys as $key) {
         # Force all keys to lower case, because the case doesn't matter and it is
         # easier to do comparing when the case of first letter is unknown, because
         # mediawiki forces it to upper case
         $key = TranslateUtils::normaliseKey($namespace, $key);
         if (isset($hugearray[$key])) {
             if (!$ignore) {
                 $to = implode(', ', (array) $hugearray[$key]);
                 STDERR("Key {$key} already belongs to {$to}, conflict with {$id}");
             }
             if (is_array($hugearray[$key])) {
                 // Hard work is already done, just add a new reference
                 $hugearray[$key][] =& $id;
             } else {
                 // Store the actual reference, then remove it from array, to not
                 // replace the references value, but to store a array of new
                 // references instead. References are hard!
                 $value =& $hugearray[$key];
                 unset($hugearray[$key]);
                 $hugearray[$key] = array(&$value, &$id);
             }
         } else {
             $hugearray[$key] =& $id;
         }
     }
     unset($id);
     // Disconnect the previous references to this $id
 }
Example #3
0
	protected function getPotTime() {
		$defs = new MessageGroupCache( $this->group );
		return $defs->exists() ? $defs->getTimestamp() : wfTimestampNow();
	}
 /**
  * This is the detective novel. We have three sources of information:
  * - current message state in the file
  * - current message state in the wiki
  * - cached message state since cache was last build
  *   (usually after export from wiki)
  *
  * Now we must try to guess what in earth has driven the file state and
  * wiki state out of sync. Then we must compile list of events that would
  * bring those to sync. Types of events are addition, deletion, (content)
  * change and possible rename in the future. After that the list of events
  * are stored for later processing of a translation administrator, who can
  * decide what actions to take on those events to bring the state more or
  * less in sync.
  *
  * @param FileBasedMessageGroup $group
  * @param string $code Language code.
  * @param int $reason
  * @param MessageGroupCache $cache
  * @throws MWException
  */
 protected function addMessageUpdateChanges(FileBasedMessageGroup $group, $code, $reason, $cache)
 {
     /* This throws a warning if message definitions are not yet
      * cached and will read the file for definitions. */
     wfSuppressWarnings();
     $wiki = $group->initCollection($code);
     wfRestoreWarnings();
     $wiki->filter('hastranslation', false);
     $wiki->loadTranslations();
     $wikiKeys = $wiki->getMessageKeys();
     // By-pass cached message definitions
     /** @var FFS $ffs */
     $ffs = $group->getFFS();
     if ($code === $group->getSourceLanguage() && !$ffs->exists($code)) {
         $path = $group->getSourceFilePath($code);
         throw new MWException("Source message file for {$group->getId()} does not exist: {$path}");
     }
     $file = $ffs->read($code);
     // Does not exist
     if ($file === false) {
         return;
     }
     // Something went wrong
     if (!isset($file['MESSAGES'])) {
         $id = $group->getId();
         $ffsClass = get_class($ffs);
         error_log("{$id} has an FFS ({$ffsClass}) - it didn't return cake for {$code}");
         return;
     }
     $fileKeys = array_keys($file['MESSAGES']);
     $common = array_intersect($fileKeys, $wikiKeys);
     $supportsFuzzy = $ffs->supportsFuzzy();
     foreach ($common as $key) {
         $sourceContent = $file['MESSAGES'][$key];
         /** @var TMessage $wikiMessage */
         $wikiMessage = $wiki[$key];
         $wikiContent = $wikiMessage->translation();
         // If FFS doesn't support it, ignore fuzziness as difference
         $wikiContent = str_replace(TRANSLATE_FUZZY, '', $wikiContent);
         // But if it does, ensure we have exactly one fuzzy marker prefixed
         if ($supportsFuzzy === 'yes' && $wikiMessage->hasTag('fuzzy')) {
             $wikiContent = TRANSLATE_FUZZY . $wikiContent;
         }
         if (self::compareContent($sourceContent, $wikiContent)) {
             // File and wiki stage agree, nothing to do
             continue;
         }
         // Check against interim cache to see whether we have changes
         // in the wiki, in the file or both.
         if ($reason !== MessageGroupCache::NO_CACHE) {
             $cacheContent = $cache->get($key);
             /* We want to ignore the common situation that the string
              * in the wiki has been changed since the last export.
              * Hence we check that source === cache && cache !== wiki
              * and if so we skip this string. */
             if (!self::compareContent($wikiContent, $cacheContent) && self::compareContent($sourceContent, $cacheContent)) {
                 continue;
             }
         }
         $this->addChange('change', $code, $key, $sourceContent);
     }
     $added = array_diff($fileKeys, $wikiKeys);
     foreach ($added as $key) {
         $sourceContent = $file['MESSAGES'][$key];
         if (trim($sourceContent) === '') {
             continue;
         }
         $this->addChange('addition', $code, $key, $sourceContent);
     }
     /* Should the cache not exist, don't consider the messages
      * missing from the file as deleted - they probably aren't
      * yet exported. For example new language translations are
      * exported the first time. */
     if ($reason !== MessageGroupCache::NO_CACHE) {
         $deleted = array_diff($wikiKeys, $fileKeys);
         foreach ($deleted as $key) {
             if ($cache->get($key) === false) {
                 /* This message has never existed in the cache, so it
                  * must be a newly made in the wiki. */
                 continue;
             }
             $this->addChange('deletion', $code, $key, null);
         }
     }
 }
 /**
  * @param string $key Message key
  * @param string $code Language code
  * @return string|null
  */
 public function getMessage($key, $code)
 {
     $cache = new MessageGroupCache($this, $code);
     if ($cache->exists()) {
         $msg = $cache->get($key);
         if ($msg !== false) {
             return $msg;
         }
         // Try harder
         $nkey = str_replace(' ', '_', strtolower($key));
         $keys = $cache->getKeys();
         foreach ($keys as $k) {
             if ($nkey === str_replace(' ', '_', strtolower($k))) {
                 return $cache->get($k);
             }
         }
         return null;
     } else {
         return null;
     }
 }
Example #6
0
	public function initCollection( $code ) {
		$messages = array();

		foreach ( $this->getGroups() as $group ) {
			$cache = new MessageGroupCache( $group );
			if ( $cache->exists() ) {
				foreach ( $cache->getKeys() as $key ) {
					$messages[$key] = $cache->get( $key );
				}
			} else {
				// BC for MessageGroupOld
				$messages += $group->load( $this->getSourceLanguage() );
			}
		}

		$namespace = $this->getNamespace();
		$definitions = new MessageDefinitions( $messages, $namespace );
		$collection = MessageCollection::newFromDefinitions( $definitions, $code );

		$this->setTags( $collection );

		return $collection;
	}
 protected function processSubmit()
 {
     $req = $this->getRequest();
     $out = $this->getOutput();
     $jobs = array();
     $jobs[] = MessageIndexRebuildJob::newJob();
     $changefile = TranslateUtils::cacheFile(self::CHANGEFILE);
     $reader = CdbReader::open($changefile);
     $groups = unserialize($reader->get('#keys'));
     $postponed = array();
     foreach ($groups as $groupId) {
         $group = MessageGroups::getGroup($groupId);
         $changes = unserialize($reader->get($groupId));
         foreach ($changes as $code => $subchanges) {
             foreach ($subchanges as $type => $messages) {
                 foreach ($messages as $index => $params) {
                     $id = self::changeId($groupId, $code, $type, $params['key']);
                     if ($req->getVal($id) === null) {
                         // We probably hit the limit with number of post parameters.
                         $postponed[$groupId][$code][$type][$index] = $params;
                         continue;
                     }
                     if ($type === 'deletion' || $req->getCheck("i/{$id}")) {
                         continue;
                     }
                     $fuzzy = $req->getCheck("f/{$id}") ? 'fuzzy' : false;
                     $key = $params['key'];
                     $title = Title::makeTitleSafe($group->getNamespace(), "{$key}/{$code}");
                     $jobs[] = MessageUpdateJob::newJob($title, $params['content'], $fuzzy);
                 }
             }
             if (!isset($postponed[$groupId][$code])) {
                 $cache = new MessageGroupCache($groupId, $code);
                 $cache->create();
             }
         }
     }
     JobQueueGroup::singleton()->push($jobs);
     $reader->close();
     rename($changefile, $changefile . '-' . wfTimestamp());
     if (count($postponed)) {
         $changefile = TranslateUtils::cacheFile(self::CHANGEFILE);
         $writer = CdbWriter::open($changefile);
         $keys = array_keys($postponed);
         $writer->set('#keys', serialize($keys));
         foreach ($postponed as $groupId => $changes) {
             $writer->set($groupId, serialize($changes));
         }
         $writer->close();
         $this->showChanges(true, $this->getLimit());
     } else {
         $out->addWikiMsg('translate-smg-submitted');
     }
 }
 /**
  * @param $group MessageGroup
  */
 public function doModLangs($group)
 {
     global $wgLang;
     $languages = array_keys(Language::getLanguageNames(false));
     $modified = $codes = array();
     foreach ($languages as $code) {
         if ($code === 'en') {
             continue;
         }
         $cache = new MessageGroupCache($group, $code);
         if ($cache->isValid()) {
             continue;
         }
         $link = $this->skin->link($this->getTitle(), htmlspecialchars(TranslateUtils::getLanguageName($code, false, $wgLang->getCode()) . " ({$code})"), array(), array('group' => $group->getId(), 'language' => $code));
         if (!$cache->exists()) {
             $modified[] = wfMsgHtml('translate-manage-modlang-new', $link);
         } else {
             $modified[] = $link;
         }
         $codes[] = $code;
     }
     if (count($modified)) {
         $this->out->addWikiMsg('translate-manage-modlangs', $wgLang->formatNum(count($modified)));
         if ($this->user->isAllowed('translate-manage')) {
             $this->out->addHTML($this->rebuildButton($group, $codes, 'import'));
         }
         $this->out->addHTML('<ul><li>' . implode("</li>\n<li>", $modified) . '</li></ul>');
     }
 }