public function testGetNamespaceString() { $conf = $this->groupConfiguration; $conf['BASIC']['namespace'] = 'image'; $this->group = MessageGroupBase::factory($conf); $this->assertEquals(NS_IMAGE, $this->group->getNamespace(), "should parse string namespace name."); }
/** * 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; }
/** * Do some conflict resolution for translations. * @param string $code Language code. * @param bool|int $startTs Time of the last export (changes in wiki after * this will conflict) * @param bool|int $endTs Time of the last export (changes in source before * this won't conflict) * @param bool|int $changeTs When change happened in the source. */ public function checkConflicts($code, $startTs = false, $endTs = false, $changeTs = false) { $messages = $this->group->load($code); if (!count($messages)) { return; } $collection = $this->group->initCollection($code); $collection->filter('ignored'); $collection->loadTranslations(); foreach ($messages as $key => $translation) { if (!isset($collection[$key])) { continue; } // @todo Temporary exception. Should be fixed elsewhere more generically. if ($translation == '{{PLURAL:GETTEXT|}}') { return; } $title = Title::makeTitleSafe($this->group->getNamespace(), "{$key}/{$code}"); $page = $title->getPrefixedText(); if ($collection[$key]->translation() === null) { $this->reportProgress("Importing {$page} as a new translation\n", 'importing'); $this->import($title, $translation, 'Importing a new translation'); continue; } $current = str_replace(TRANSLATE_FUZZY, '', $collection[$key]->translation()); $translation = str_replace(TRANSLATE_FUZZY, '', $translation); if ($translation === $current) { continue; } $this->reportProgress("Conflict in " . $this->color('bold', $page) . "!", $page); $iso = 'xnY-xnm-xnd"T"xnH:xni:xns'; $lang = RequestContext::getMain()->getLanguage(); // Finally all is ok, now lets start comparing timestamps // Make sure we are comparing timestamps in same format $wikiTs = $this->getLastGoodChange($title, $startTs); if ($wikiTs) { $wikiTs = wfTimestamp(TS_UNIX, $wikiTs); $wikiDate = $lang->sprintfDate($iso, wfTimestamp(TS_MW, $wikiTs)); } else { $wikiDate = 'Unknown'; } if ($startTs) { $startTs = wfTimestamp(TS_UNIX, $startTs); } if ($endTs) { $endTs = wfTimestamp(TS_UNIX, $endTs); } if ($changeTs) { $changeTs = wfTimestamp(TS_UNIX, $changeTs); $changeDate = $lang->sprintfDate($iso, wfTimestamp(TS_MW, $changeTs)); } else { $changeDate = 'Unknown'; } if ($changeTs) { if ($wikiTs > $startTs && $changeTs <= $endTs) { $this->reportProgress(" →Changed in wiki after export: IGNORE", $page); continue; } elseif (!$wikiTs || $changeTs > $endTs && $wikiTs < $startTs) { $this->reportProgress(" →Changed in source after export: IMPORT", $page); $this->import($title, $translation, 'Updating translation from external source'); continue; } } if (!$this->interactive) { continue; } $this->reportProgress(" →Needs manual resolution", $page); $this->reportProgress("Source translation at {$changeDate}:", 'source'); $this->reportProgress($this->color('blue', $translation), 'source'); $this->reportProgress("Wiki translation at {$wikiDate}:", 'translation'); $this->reportProgress($this->color('green', $current), 'translation'); do { $this->reportProgress("Resolution: [S]kip [I]mport [C]onflict: ", 'foo'); // @todo Find an elegant way to use Maintenance::readconsole(). $action = fgets(STDIN); $action = strtoupper(trim($action)); if ($action === 'S') { break; } if ($action === 'I') { $this->import($title, $translation, 'Updating translation from external source'); break; } if ($action === 'C') { $this->import($title, TRANSLATE_FUZZY . $translation, 'Edit conflict between wiki and source'); break; } } while (true); } }
/** * @param MessageGroup $group * @param string $code * @param string $type * @param array $params * @param int $limit * @return string HTML */ protected function formatChange(MessageGroup $group, $code, $type, $params, &$limit) { $key = $params['key']; $title = Title::makeTitleSafe($group->getNamespace(), "{$key}/{$code}"); $id = self::changeId($group->getId(), $code, $type, $key); if ($title && $title->exists() && $type === 'addition') { // The message has for some reason dropped out from cache // or perhaps it is being reused. In any case treat it // as a change for display, so the admin can see if // action is needed and let the message be processed. // Otherwise it will end up in the postponed category // forever and will prevent rebuilding the cache, which // leads to many other annoying problems. $type = 'change'; } elseif ($title && !$title->exists() && ($type === 'deletion' || $type === 'change')) { return ''; } $text = ''; if ($type === 'deletion') { $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent()); $oldContent = ContentHandler::makeContent($wiki, $title); $newContent = ContentHandler::makeContent('', $title); $this->diff->setContent($oldContent, $newContent); $text = $this->diff->getDiff(Linker::link($title), ''); } elseif ($type === 'addition') { $oldContent = ContentHandler::makeContent('', $title); $newContent = ContentHandler::makeContent($params['content'], $title); $this->diff->setContent($oldContent, $newContent); $text = $this->diff->getDiff('', Linker::link($title)); } elseif ($type === 'change') { $wiki = ContentHandler::getContentText(Revision::newFromTitle($title)->getContent()); $handle = new MessageHandle($title); if ($handle->isFuzzy()) { $wiki = '!!FUZZY!!' . str_replace(TRANSLATE_FUZZY, '', $wiki); } $label = $this->msg('translate-manage-action-ignore')->text(); $actions = Xml::checkLabel($label, "i/{$id}", "i/{$id}"); $limit--; if ($group->getSourceLanguage() === $code) { $label = $this->msg('translate-manage-action-fuzzy')->text(); $actions .= ' ' . Xml::checkLabel($label, "f/{$id}", "f/{$id}", true); $limit--; } $oldContent = ContentHandler::makeContent($wiki, $title); $newContent = ContentHandler::makeContent($params['content'], $title); $this->diff->setContent($oldContent, $newContent); $text .= $this->diff->getDiff(Linker::link($title), $actions); } $hidden = Html::hidden($id, 1); $limit--; $text .= $hidden; $classes = "mw-translate-smg-change smg-change-{$type}"; if ($limit < 0) { // Don't add if one of the fields might get dropped of at submission return ''; } return Html::rawElement('div', array('class' => $classes), $text); }
/** * Given a group, message key and language code, creates a title for the * translation page. * * @param MessageGroup $group * @param string $key Message key * @param string $code Language code * @return Title */ public static function makeTranslationTitle($group, $key, $code) { $ns = $group->getNamespace(); return Title::makeTitleSafe($ns, "{$key}/{$code}"); }