summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'MLEB/Translate/specials')
-rw-r--r--MLEB/Translate/specials/SpecialAggregateGroups.php287
-rw-r--r--MLEB/Translate/specials/SpecialExportTranslations.php5
-rw-r--r--MLEB/Translate/specials/SpecialImportTranslations.php3
-rw-r--r--MLEB/Translate/specials/SpecialLanguageStats.php20
-rw-r--r--MLEB/Translate/specials/SpecialManageGroups.php110
-rw-r--r--MLEB/Translate/specials/SpecialMessageGroupStats.php2
-rw-r--r--MLEB/Translate/specials/SpecialSearchTranslations.php3
-rw-r--r--MLEB/Translate/specials/SpecialTranslate.php4
-rw-r--r--MLEB/Translate/specials/SpecialTranslationStats.php298
-rw-r--r--MLEB/Translate/specials/SpecialTranslations.php7
10 files changed, 109 insertions, 630 deletions
diff --git a/MLEB/Translate/specials/SpecialAggregateGroups.php b/MLEB/Translate/specials/SpecialAggregateGroups.php
deleted file mode 100644
index afc39032..00000000
--- a/MLEB/Translate/specials/SpecialAggregateGroups.php
+++ /dev/null
@@ -1,287 +0,0 @@
-<?php
-/**
- * Contains logic for special page Special:AggregateGroups.
- *
- * @file
- * @author Santhosh Thottingal
- * @author Niklas Laxström
- * @author Siebrand Mazeland
- * @author Kunal Grover
- * @license GPL-2.0-or-later
- */
-
-class SpecialAggregateGroups extends SpecialPage {
- protected $hasPermission = false;
-
- public function __construct() {
- parent::__construct( 'AggregateGroups', 'translate-manage' );
- }
-
- protected function getGroupName() {
- return 'translation';
- }
-
- public function execute( $parameters ) {
- $this->setHeaders();
- $this->addHelpLink( 'Help:Extension:Translate/Page translation administration' );
-
- $out = $this->getOutput();
- $out->addModuleStyles( 'ext.translate.specialpages.styles' );
-
- // Check permissions
- if ( $this->getUser()->isAllowed( 'translate-manage' ) ) {
- $this->hasPermission = true;
- }
-
- $groupsPreload = array_merge(
- MessageGroups::getGroupsByType( WikiPageMessageGroup::class ),
- MessageGroups::getGroupsByType( AggregateMessageGroup::class )
- );
- TranslateMetadata::preloadGroups( array_keys( $groupsPreload ) );
-
- $groups = MessageGroups::getAllGroups();
- uasort( $groups, [ MessageGroups::class, 'groupLabelSort' ] );
- $aggregates = [];
- $pages = [];
- foreach ( $groups as $group ) {
- if ( $group instanceof WikiPageMessageGroup ) {
- $pages[] = $group;
- } elseif ( $group instanceof AggregateMessageGroup ) {
- $subgroups = TranslateMetadata::getSubgroups( $group->getId() );
- if ( $subgroups !== null ) {
- $aggregates[] = $group;
- }
- }
- }
-
- if ( !count( $pages ) ) {
- // @todo Use different message
- $out->addWikiMsg( 'tpt-list-nopages' );
-
- return;
- }
-
- $this->showAggregateGroups( $aggregates );
- }
-
- /**
- * @param AggregateMessageGroup $group
- * @return string
- */
- protected function showAggregateGroup( $group ) {
- $out = '';
- $id = $group->getId();
- $label = $group->getLabel();
- $desc = $group->getDescription( $this->getContext() );
-
- $div = Html::openElement( 'div', [
- 'class' => 'mw-tpa-group',
- 'data-groupid' => $id,
- 'data-id' => $this->htmlIdForGroup( $group ),
- ] );
-
- $out .= $div;
-
- $edit = '';
- $remove = '';
- $editGroup = '';
- $select = '';
- $addButton = '';
-
- // Add divs for editing Aggregate Groups
- if ( $this->hasPermission ) {
- // Group edit and remove buttons
- $edit = Html::element( 'span', [ 'class' => 'tp-aggregate-edit-ag-button' ] );
- $remove = Html::element( 'span', [ 'class' => 'tp-aggregate-remove-ag-button' ] );
-
- // Edit group div
- $editGroupNameLabel = $this->msg( 'tpt-aggregategroup-edit-name' )->escaped();
- $editGroupName = Html::input(
- 'tp-agg-name',
- $label,
- 'text',
- [ 'class' => 'tp-aggregategroup-edit-name', 'maxlength' => '200' ]
- );
- $editGroupDescriptionLabel = $this->msg( 'tpt-aggregategroup-edit-description' )->escaped();
- $editGroupDescription = Html::input(
- 'tp-agg-desc',
- $desc,
- 'text',
- [ 'class' => 'tp-aggregategroup-edit-description' ]
- );
- $saveButton = Xml::submitButton(
- $this->msg( 'tpt-aggregategroup-update' )->text(),
- [ 'class' => 'tp-aggregategroup-update' ]
- );
- $cancelButton = Xml::submitButton(
- $this->msg( 'tpt-aggregategroup-update-cancel' )->text(),
- [ 'class' => 'tp-aggregategroup-update-cancel' ]
- );
- $editGroup = Html::rawElement(
- 'div',
- [
- 'class' => 'tp-edit-group hidden'
- ],
- $editGroupNameLabel .
- $editGroupName . '<br />' .
- $editGroupDescriptionLabel .
- $editGroupDescription .
- $saveButton .
- $cancelButton
- );
-
- // Subgroups selector
- $select = Html::input(
- 'tp-subgroups-input',
- '',
- 'text',
- [ 'class' => 'tp-group-input' ]
- );
- $addButton = Html::element( 'input',
- [ 'type' => 'button',
- 'value' => $this->msg( 'tpt-aggregategroup-add' )->text(),
- 'class' => 'tp-aggregate-add-button' ]
- );
- }
-
- // Aggregate Group info div
- $groupName = Html::rawElement( 'h2',
- [ 'class' => 'tp-name' ],
- htmlspecialchars( $label ) . $edit . $remove
- );
- $groupDesc = Html::element( 'p',
- [ 'class' => 'tp-desc' ],
- $desc
- );
- $groupInfo = Html::rawElement( 'div',
- [ 'class' => 'tp-display-group' ],
- $groupName .
- $groupDesc
- );
-
- $out .= $groupInfo;
- $out .= $editGroup;
- $out .= $this->listSubgroups( $group );
- $out .= $select . $addButton;
- $out .= '</div>';
-
- return $out;
- }
-
- /** @param array $aggregates */
- protected function showAggregateGroups( array $aggregates ) {
- $out = $this->getOutput();
- $out->addModules( 'ext.translate.special.aggregategroups' );
-
- $nojs = Html::element(
- 'div',
- [ 'class' => 'tux-nojs errorbox' ],
- $this->msg( 'tux-nojs' )->plain()
- );
-
- $out->addHTML( $nojs );
-
- /** @var AggregateMessageGroup $group */
- foreach ( $aggregates as $group ) {
- $out->addHTML( $this->showAggregateGroup( $group ) );
- }
-
- // Add new group if user has permissions
- if ( $this->hasPermission ) {
- $out->addHTML( "<br/><a class='tpt-add-new-group' href='#'>" .
- $this->msg( 'tpt-aggregategroup-add-new' )->escaped() .
- '</a>' );
- $newGroupNameLabel = $this->msg( 'tpt-aggregategroup-new-name' )->escaped();
- $newGroupName = Html::element(
- 'input',
- [ 'class' => 'tp-aggregategroup-add-name', 'maxlength' => '200' ]
- );
- $newGroupDescriptionLabel = $this->msg( 'tpt-aggregategroup-new-description' )->escaped();
- $newGroupDescription = Html::element( 'input',
- [ 'class' => 'tp-aggregategroup-add-description' ]
- );
- $saveButton = Html::element( 'input', [
- 'type' => 'button',
- 'value' => $this->msg( 'tpt-aggregategroup-save' )->text(),
- 'id' => 'tpt-aggregategroups-save',
- 'class' => 'tp-aggregate-save-button'
- ] );
- $newGroupDiv = Html::rawElement(
- 'div',
- [ 'class' => 'tpt-add-new-group hidden' ],
- "$newGroupNameLabel $newGroupName<br />" .
- "$newGroupDescriptionLabel $newGroupDescription<br />$saveButton"
- );
- $out->addHTML( $newGroupDiv );
- }
- }
-
- /**
- * @param AggregateMessageGroup $parent
- * @return string
- */
- protected function listSubgroups( AggregateMessageGroup $parent ) {
- $id = $this->htmlIdForGroup( $parent, 'mw-tpa-grouplist-' );
- $out = Html::openElement( 'ol', [ 'id' => $id ] );
-
- // Not calling $parent->getGroups() because it has done filtering already
- $subgroupIds = TranslateMetadata::getSubgroups( $parent->getId() ) ?? [];
-
- // Get the respective groups and sort them
- $subgroups = MessageGroups::getGroupsById( $subgroupIds );
- '@phan-var WikiPageMessageGroup[] $subgroups';
- uasort( $subgroups, [ MessageGroups::class, 'groupLabelSort' ] );
-
- // Avoid potentially thousands of separate database queries
- $lb = new LinkBatch();
- foreach ( $subgroups as $group ) {
- $lb->addObj( $group->getTitle() );
- }
- $lb->setCaller( __METHOD__ );
- $lb->execute();
-
- // Add missing invalid group ids back, not returned by getGroupsById
- foreach ( $subgroupIds as $id ) {
- if ( !isset( $subgroups[$id] ) ) {
- $subgroups[$id] = null;
- }
- }
-
- foreach ( $subgroups as $id => $group ) {
- $remove = '';
- if ( $this->hasPermission ) {
- $remove = Html::element( 'span',
- [
- 'class' => 'tp-aggregate-remove-button',
- 'data-groupid' => $id,
- ]
- );
- }
-
- if ( $group ) {
- $text = $this->getLinkRenderer()->makeKnownLink( $group->getTitle() );
- $note = MessageGroups::getPriority( $id );
- } else {
- $text = htmlspecialchars( $id );
- $note = $this->msg( 'tpt-aggregategroup-invalid-group' )->escaped();
- }
-
- $out .= Html::rawElement( 'li', [], "$text$remove $note" );
- }
- $out .= Html::closeElement( 'ol' );
-
- return $out;
- }
-
- /**
- * @param MessageGroup $group
- * @param string $prefix
- * @return string
- */
- protected function htmlIdForGroup( MessageGroup $group, $prefix = '' ) {
- $id = sha1( $group->getId() );
- $id = substr( $id, 5, 8 );
-
- return $prefix . $id;
- }
-}
diff --git a/MLEB/Translate/specials/SpecialExportTranslations.php b/MLEB/Translate/specials/SpecialExportTranslations.php
index 2e39f3c0..15add963 100644
--- a/MLEB/Translate/specials/SpecialExportTranslations.php
+++ b/MLEB/Translate/specials/SpecialExportTranslations.php
@@ -189,7 +189,10 @@ class SpecialExportTranslations extends SpecialPage {
}
if ( !$ffs instanceof GettextFFS ) {
- $group = FileBasedMessageGroup::newFromMessageGroup( $group );
+ if ( !$group instanceof FileBasedMessageGroup ) {
+ $group = FileBasedMessageGroup::newFromMessageGroup( $group );
+ }
+
$ffs = new GettextFFS( $group );
}
diff --git a/MLEB/Translate/specials/SpecialImportTranslations.php b/MLEB/Translate/specials/SpecialImportTranslations.php
index eea01221..a3b472d0 100644
--- a/MLEB/Translate/specials/SpecialImportTranslations.php
+++ b/MLEB/Translate/specials/SpecialImportTranslations.php
@@ -41,8 +41,6 @@ class SpecialImportTranslations extends SpecialPage {
// Security and validity checks
if ( !$this->userCanExecute( $this->getUser() ) ) {
$this->displayRestrictionError();
-
- return;
}
if ( !$this->getRequest()->wasPosted() ) {
@@ -98,6 +96,7 @@ class SpecialImportTranslations extends SpecialPage {
}
$importer = new MessageWebImporter( $this->getPageTitle(), $group, $code );
+ $importer->setUser( $this->getUser() );
$alldone = $importer->execute( $messages );
if ( $alldone ) {
diff --git a/MLEB/Translate/specials/SpecialLanguageStats.php b/MLEB/Translate/specials/SpecialLanguageStats.php
index 62aa3f79..4e18239a 100644
--- a/MLEB/Translate/specials/SpecialLanguageStats.php
+++ b/MLEB/Translate/specials/SpecialLanguageStats.php
@@ -8,6 +8,8 @@
* @license GPL-2.0-or-later
*/
+use MediaWiki\Cache\LinkBatchFactory;
+
/**
* Implements includable special page Special:LanguageStats which provides
* translation statistics for all defined message groups.
@@ -67,12 +69,15 @@ class SpecialLanguageStats extends SpecialPage {
protected $statsCounted = [];
/** @var array */
protected $states;
+ /** @var LinkBatchFactory */
+ private $linkBatchFactory;
- public function __construct() {
+ public function __construct( LinkBatchFactory $linkBatchFactory ) {
parent::__construct( 'LanguageStats' );
$this->target = $this->getLanguage()->getCode();
$this->totals = MessageGroupStats::getEmptyStats();
+ $this->linkBatchFactory = $linkBatchFactory;
}
public function isIncludable() {
@@ -398,7 +403,16 @@ class SpecialLanguageStats extends SpecialPage {
$this->addWorkflowStatesColumn();
$out = '';
- TranslateMetadata::preloadGroups( array_keys( MessageGroups::getAllGroups() ) );
+ // This avoids a database query per translatable page, which would be caused by
+ // $group->getSourceLanguage() in $this->getWorkflowStateCell without preloading
+ $lb = $this->linkBatchFactory->newLinkBatch();
+ foreach ( MessageGroups::getAllGroups() as $group ) {
+ if ( $group instanceof WikiPageMessageGroup ) {
+ $lb->addObj( $group->getTitle() );
+ }
+ }
+ $lb->setCaller( __METHOD__ )->execute();
+
$structure = MessageGroups::getGroupStructure();
foreach ( $structure as $item ) {
$out .= $this->makeGroupGroup( $item, $stats );
@@ -467,7 +481,7 @@ class SpecialLanguageStats extends SpecialPage {
) {
$groupId = $group->getId();
- if ( $this->table->isExcluded( $groupId, $this->target ) !== null ) {
+ if ( $this->table->isExcluded( $groupId, $this->target ) ) {
return '';
}
diff --git a/MLEB/Translate/specials/SpecialManageGroups.php b/MLEB/Translate/specials/SpecialManageGroups.php
index 5db58fa2..cec2b8ce 100644
--- a/MLEB/Translate/specials/SpecialManageGroups.php
+++ b/MLEB/Translate/specials/SpecialManageGroups.php
@@ -5,6 +5,7 @@ use MediaWiki\Extension\Translate\MessageSync\MessageSourceChange;
use MediaWiki\Extension\Translate\Synchronization\DisplayGroupSynchronizationInfo;
use MediaWiki\Extension\Translate\Synchronization\GroupSynchronizationCache;
use MediaWiki\Extension\Translate\Synchronization\MessageUpdateParameter;
+use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\RevisionLookup;
use MediaWiki\Revision\SlotRecord;
@@ -170,7 +171,8 @@ class SpecialManageGroups extends SpecialPage {
// The above count as three
$limit -= 3;
- if ( $this->getConfig()->get( 'TranslateGroupSynchronizationCache' ) ) {
+ $groupSyncCacheEnabled = $this->getConfig()->get( 'TranslateGroupSynchronizationCache' );
+ if ( $groupSyncCacheEnabled ) {
$out->addHTML(
$this->displayGroupSyncInfo->getGroupsInSyncHtml(
$this->synchronizationCache->getGroupsInSync(),
@@ -195,6 +197,12 @@ class SpecialManageGroups extends SpecialPage {
);
$out->addHTML( Html::element( 'h2', [], $group->getLabel() ) );
+ if ( $groupSyncCacheEnabled && $this->synchronizationCache->groupHasErrors( $id ) ) {
+ $out->addHTML(
+ Html::warningBox( $this->msg( 'translate-smg-group-sync-error-warn' )->escaped(), 'center' )
+ );
+ }
+
// Reduce page existance queries to one per group
$lb = new LinkBatch();
$ns = $group->getNamespace();
@@ -267,6 +275,7 @@ class SpecialManageGroups extends SpecialPage {
$title = Title::makeTitleSafe( $group->getNamespace(), "$key/$language" );
$id = self::changeId( $group->getId(), $language, $type, $key );
$noticeHtml = '';
+ $isReusedKey = false;
if ( $title && $type === 'addition' && $title->exists() ) {
// The message has for some reason dropped out from cache
@@ -278,6 +287,7 @@ class SpecialManageGroups extends SpecialPage {
// leads to many other annoying problems.
$type = 'change';
$noticeHtml .= Html::warningBox( $this->msg( 'translate-manage-key-reused' )->text() );
+ $isReusedKey = true;
} elseif ( $title && ( $type === 'deletion' || $type === 'change' ) && !$title->exists() ) {
// This happens if a message key has been renamed
// The change can be ignored.
@@ -288,11 +298,10 @@ class SpecialManageGroups extends SpecialPage {
$titleLink = $this->getLinkRenderer()->makeLink( $title );
if ( $type === 'deletion' ) {
- $wiki = ContentHandler::getContentText(
- $this->revLookup
- ->getRevisionByTitle( $title )
- ->getContent( SlotRecord::MAIN )
- );
+ $content = $this->revLookup
+ ->getRevisionByTitle( $title )
+ ->getContent( SlotRecord::MAIN );
+ $wiki = ( $content instanceof TextContent ) ? $content->getText() : '';
if ( $wiki === '' ) {
$noticeHtml .= Html::warningBox(
@@ -348,18 +357,35 @@ class SpecialManageGroups extends SpecialPage {
$actions = '';
$importSelected = true;
- if ( $group->getSourceLanguage() === $language ) {
+ $sourceLanguage = $group->getSourceLanguage();
+
+ if ( $sourceLanguage === $language ) {
$importSelected = false;
$label = $this->msg( 'translate-manage-action-fuzzy' )->text();
$actions .= Xml::radioLabel( $label, "msg/$id", "fuzzy", "f/$id", true );
}
- $label = $this->msg( 'translate-manage-action-import' )->text();
- $actions .= Xml::radioLabel( $label, "msg/$id", "import", "imp/$id", $importSelected );
+ if (
+ $sourceLanguage !== $language &&
+ $isReusedKey &&
+ !self::isMessageDefinitionPresent( $group, $changes, $key )
+ ) {
+ $noticeHtml .= Html::warningBox(
+ $this->msg( 'translate-manage-source-message-not-found' )->text(),
+ 'mw-translate-smg-notice-important'
+ );
- $label = $this->msg( 'translate-manage-action-ignore' )->text();
- $actions .= Xml::radioLabel( $label, "msg/$id", "ignore", "i/$id" );
- $limit--;
+ // Automatically ignore messages that don't have a definitions
+ $actions .= Html::hidden( "msg/$id", 'ignore', [ 'id' => "i/$id" ] );
+ $limit--;
+ } else {
+ $label = $this->msg( 'translate-manage-action-import' )->text();
+ $actions .= Xml::radioLabel( $label, "msg/$id", "import", "imp/$id", $importSelected );
+
+ $label = $this->msg( 'translate-manage-action-ignore' )->text();
+ $actions .= Xml::radioLabel( $label, "msg/$id", "ignore", "i/$id" );
+ $limit--;
+ }
$oldContent = ContentHandler::makeContent( $wiki, $title );
$newContent = ContentHandler::makeContent( $params['content'], $title );
@@ -396,13 +422,18 @@ class SpecialManageGroups extends SpecialPage {
$reader = \Cdb\Reader::open( $this->cdb );
$groups = $this->getGroupsFromCdb( $reader );
+ $groupSyncCacheEnabled = $this->getConfig()->get( 'TranslateGroupSynchronizationCache' );
$postponed = [];
foreach ( $groups as $groupId => $group ) {
try {
- $sourceChanges = MessageSourceChange::loadModifications(
- TranslateUtils::deserialize( $reader->get( $groupId ) )
- );
+ $changes = TranslateUtils::deserialize( $reader->get( $groupId ) );
+ if ( $groupSyncCacheEnabled && $this->synchronizationCache->groupHasErrors( $groupId ) ) {
+ $postponed[$groupId] = $changes;
+ continue;
+ }
+
+ $sourceChanges = MessageSourceChange::loadModifications( $changes );
$groupModificationJobs = [];
$groupRenameJobData = [];
$languages = $sourceChanges->getLanguages();
@@ -433,6 +464,10 @@ class SpecialManageGroups extends SpecialPage {
}
}
+ if ( $groupSyncCacheEnabled && !isset( $postponed[ $groupId ] ) ) {
+ $this->synchronizationCache->markGroupAsReviewed( $groupId );
+ }
+
$modificationJobs[$groupId] = $groupModificationJobs;
$renameJobData[$groupId] = $groupRenameJobData;
} catch ( Exception $e ) {
@@ -504,13 +539,10 @@ class SpecialManageGroups extends SpecialPage {
return;
}
- $skin->getOutput()->addModuleStyles( 'ext.translate.tabgroup' );
-
$tabs['namespaces'] = [];
foreach ( $pagesInGroup as $spName => $section ) {
$spClass = $specialPageFactory->getPage( $spName );
- // DisabledSpecialPage was added in MW 1.33
if ( $spClass === null || $spClass instanceof DisabledSpecialPage ) {
continue; // Page explicitly disabled
}
@@ -558,7 +590,9 @@ class SpecialManageGroups extends SpecialPage {
): void {
$changes = $sourceChanges->getRenames( $language );
foreach ( $changes as $key => $params ) {
- if ( !isset( $changes[$key] ) ) {
+ // Since we're removing items from the array within the loop add
+ // a check here to ensure that the current key is still set.
+ if ( !isset( $changes[ $key ] ) ) {
continue;
}
@@ -753,7 +787,9 @@ class SpecialManageGroups extends SpecialPage {
$groupNamespace = $group->getNamespace();
foreach ( $renames as $key => $params ) {
- if ( !isset( $renames[ $key] ) ) {
+ // Since we're removing items from the array within the loop add
+ // a check here to ensure that the current key is still set.
+ if ( !isset( $renames[$key] ) ) {
continue;
}
@@ -943,13 +979,12 @@ class SpecialManageGroups extends SpecialPage {
return [ false, $isCurrentKeyPresent ];
}
- if ( $isSourceLang === false && $sourceChanges->isEqual( $language, $matchedKey ) ) {
- // For non source language, if strings are equal, they are not shown on the UI
- // and hence not submitted.
- return [ false, $isCurrentKeyPresent ];
- }
-
- return [ true, $isCurrentKeyPresent ];
+ // For non source language, if strings are equal, they are not shown on the UI
+ // and hence not submitted.
+ return [
+ $isSourceLang || !$sourceChanges->isEqual( $language, $matchedKey ),
+ $isCurrentKeyPresent
+ ];
}
private function getProcessingErrorMessage( array $errorGroups, int $totalGroupCount ): string {
@@ -1037,11 +1072,26 @@ class SpecialManageGroups extends SpecialPage {
if ( $this->getConfig()->get( 'TranslateGroupSynchronizationCache' ) ) {
$this->synchronizationCache->addMessages( $groupId, ...$messages );
$this->synchronizationCache->markGroupForSync( $groupId );
+
+ LoggerFactory::getInstance( 'Translate.GroupSynchronization' )->info(
+ '[' . __CLASS__ . '] Synchronization started for {groupId} by {user}',
+ [
+ 'groupId' => $groupId,
+ 'user' => $this->getUser()->getName()
+ ]
+ );
}
- $jobQueueInstance->push( $groupJobs );
- }
+ // There is posibility for a race condition here: the translate_cache table / group sync
+ // cache is not yet populated with the messages to be processed, but the jobs start
+ // running and try to remove the message from the cache. This results in a "Key not found"
+ // error. Avoid this condition by using a DeferredUpdate.
+ DeferredUpdates::addCallableUpdate(
+ static function () use ( $jobQueueInstance, $groupJobs ) {
+ $jobQueueInstance->push( $groupJobs );
+ }
+ );
- $jobQueueInstance->push( MessageIndexRebuildJob::newJob() );
+ }
}
}
diff --git a/MLEB/Translate/specials/SpecialMessageGroupStats.php b/MLEB/Translate/specials/SpecialMessageGroupStats.php
index 338f70c0..8bf25814 100644
--- a/MLEB/Translate/specials/SpecialMessageGroupStats.php
+++ b/MLEB/Translate/specials/SpecialMessageGroupStats.php
@@ -146,7 +146,7 @@ class SpecialMessageGroupStats extends SpecialLanguageStats {
sort( $languages );
$this->filterPriorityLangs( $languages, $this->target, $stats );
foreach ( $languages as $code ) {
- if ( $table->isExcluded( $this->target, $code ) !== null ) {
+ if ( $table->isExcluded( $this->target, $code ) ) {
continue;
}
$out .= $this->makeRow( $code, $stats );
diff --git a/MLEB/Translate/specials/SpecialSearchTranslations.php b/MLEB/Translate/specials/SpecialSearchTranslations.php
index dd6fcd1d..bc129579 100644
--- a/MLEB/Translate/specials/SpecialSearchTranslations.php
+++ b/MLEB/Translate/specials/SpecialSearchTranslations.php
@@ -7,6 +7,9 @@
* @license GPL-2.0-or-later
*/
+use MediaWiki\Extension\Translate\TranslatorInterface\Aid\CurrentTranslationAid;
+use MediaWiki\Extension\Translate\TranslatorInterface\Aid\TranslationAidDataProvider;
+
/**
* ...
*
diff --git a/MLEB/Translate/specials/SpecialTranslate.php b/MLEB/Translate/specials/SpecialTranslate.php
index 7294e6f0..2c20c41d 100644
--- a/MLEB/Translate/specials/SpecialTranslate.php
+++ b/MLEB/Translate/specials/SpecialTranslate.php
@@ -272,7 +272,7 @@ class SpecialTranslate extends SpecialPage {
'class' => $groupClass,
'data-msggroupid' => $this->group->getId(),
],
- $this->group->getLabel()
+ $this->group->getLabel( $this->getContext() )
) .
Html::closeElement( 'div' );
@@ -360,8 +360,6 @@ class SpecialTranslate extends SpecialPage {
return true;
}
- $skin->getOutput()->addModuleStyles( 'ext.translate.tabgroup' );
-
// Extract subpage syntax, otherwise the values are not passed forward
$params = [];
if ( trim( $sub ) !== '' ) {
diff --git a/MLEB/Translate/specials/SpecialTranslationStats.php b/MLEB/Translate/specials/SpecialTranslationStats.php
deleted file mode 100644
index abc7e085..00000000
--- a/MLEB/Translate/specials/SpecialTranslationStats.php
+++ /dev/null
@@ -1,298 +0,0 @@
-<?php
-/**
- * Contains logic for special page Special:TranslationStats.
- *
- * @file
- * @author Niklas Laxström
- * @author Siebrand Mazeland
- * @license GPL-2.0-or-later
- */
-
-use MediaWiki\Extension\Translate\Services;
-use MediaWiki\Extension\Translate\Statistics\TranslationStatsGraphOptions;
-
-/**
- * @defgroup Stats Statistics
- * Collection of code to produce various kinds of statistics.
- */
-
-/**
- * Includable special page for generating graphs on translations.
- *
- * @ingroup SpecialPage TranslateSpecialPage Stats
- */
-class SpecialTranslationStats extends SpecialPage {
-
- /** @var \MediaWiki\Extension\Translate\Statistics\TranslationStatsDataProvider */
- private $dataProvider;
-
- private const GRAPH_CONTAINER_ID = 'translationStatsGraphContainer';
-
- private const GRAPH_CONTAINER_CLASS = 'mw-translate-translationstats-container';
-
- public function __construct() {
- parent::__construct( 'TranslationStats' );
- $this->dataProvider = Services::getInstance()->getTranslationStatsDataProvider();
- }
-
- public function isIncludable() {
- return true;
- }
-
- protected function getGroupName() {
- return 'translation';
- }
-
- public function execute( $par ) {
- $graphOpts = new TranslationStatsGraphOptions();
- $graphOpts->bindArray( $this->getRequest()->getValues() );
-
- $pars = explode( ';', $par );
- foreach ( $pars as $item ) {
- if ( strpos( $item, '=' ) === false ) {
- continue;
- }
-
- list( $key, $value ) = array_map( 'trim', explode( '=', $item, 2 ) );
- if ( $graphOpts->hasValue( $key ) ) {
- $graphOpts->setValue( $key, $value );
- }
- }
-
- $graphOpts->normalize( $this->dataProvider->getGraphTypes() );
- $opts = $graphOpts->getFormOptions();
-
- if ( $this->including() ) {
- $this->getOutput()->addHTML( $this->embed( $opts ) );
- } else {
- $this->form( $opts );
- }
- }
-
- /**
- * Constructs the form which can be used to generate custom graphs.
- * @param FormOptions $opts
- * @suppress SecurityCheck-DoubleEscaped Intentionally outputting what user should type
- */
- protected function form( FormOptions $opts ) {
- global $wgScript;
- $this->setHeaders();
- $out = $this->getOutput();
- $out->addModules( 'ext.translate.special.translationstats' );
- $out->addHelpLink( 'Help:Extension:Translate/Statistics_and_reporting' );
- $out->addWikiMsg( 'translate-statsf-intro' );
- $out->addHTML(
- Xml::fieldset( $this->msg( 'translate-statsf-options' )->text() ) .
- Html::openElement( 'form', [ 'action' => $wgScript, 'id' => 'translationStatsConfig' ] ) .
- Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) .
- Html::hidden( 'preview', 1 ) .
- '<table>'
- );
- $submit = Xml::submitButton( $this->msg( 'translate-statsf-submit' )->text() );
- $out->addHTML(
- $this->eInput( 'width', $opts ) .
- $this->eInput( 'height', $opts ) .
- '<tr><td colspan="2"><hr /></td></tr>' .
- $this->eInput( 'start', $opts, 24 ) .
- $this->eInput( 'days', $opts ) .
- $this->eRadio( 'scale', $opts, [ 'months', 'weeks', 'days', 'hours' ] ) .
- $this->eRadio( 'count', $opts, $this->dataProvider->getGraphTypes() ) .
- '<tr><td colspan="2"><hr /></td></tr>' .
- $this->eLanguage( 'language', $opts ) .
- $this->eGroup( 'group', $opts ) .
- '<tr><td colspan="2"><hr /></td></tr>' .
- '<tr><td colspan="2">' . $submit . '</td></tr>'
- );
- $out->addHTML(
- '</table>' .
- '</form>' .
- '</fieldset>'
- );
- if ( !$opts['preview'] ) {
- return;
- }
- $spiParams = '';
- foreach ( $opts->getChangedValues() as $key => $v ) {
- if ( $key === 'preview' ) {
- continue;
- }
- if ( $spiParams !== '' ) {
- $spiParams .= ';';
- }
-
- if ( is_array( $v ) ) {
- $v = implode( ',', $v );
- if ( !strlen( $v ) ) {
- continue;
- }
- }
- $spiParams .= wfEscapeWikiText( "$key=$v" );
- }
- if ( $spiParams !== '' ) {
- $spiParams = '/' . $spiParams;
- }
- $titleText = $this->getPageTitle()->getPrefixedText();
- $out->addHTML(
- Html::element( 'hr' )
- );
- // Element to render the graph
- $out->addHTML(
- Html::rawElement(
- 'div',
- [
- 'id' => self::GRAPH_CONTAINER_ID ,
- 'style' => 'margin: 2em auto; display: block',
- 'class' => self::GRAPH_CONTAINER_CLASS
- ]
- )
- );
-
- $out->addHTML(
- Html::element(
- 'pre',
- [ 'aria-label' => $this->msg( 'translate-statsf-embed' )->text() ],
- "{{{$titleText}{$spiParams}}}"
- )
- );
- }
-
- /**
- * Constructs a table row with label and input in two columns.
- * @param string $name Option name.
- * @param FormOptions $opts
- * @param int $width
- * @return string Html.
- */
- protected function eInput( $name, FormOptions $opts, $width = 4 ) {
- $value = $opts[$name];
- return '<tr><td>' . $this->eLabel( $name ) . '</td><td>' .
- Xml::input( $name, $width, $value, [ 'id' => $name ] ) .
- '</td></tr>' . "\n";
- }
-
- /**
- * Constructs a label for option.
- * @param string $name Option name.
- * @return string Html.
- */
- protected function eLabel( $name ) {
- // Give grep a chance to find the usages:
- // translate-statsf-width, translate-statsf-height, translate-statsf-start,
- // translate-statsf-days, translate-statsf-scale, translate-statsf-count,
- // translate-statsf-language, translate-statsf-group
- $label = 'translate-statsf-' . $name;
- $label = $this->msg( $label )->escaped();
- return Xml::tags( 'label', [ 'for' => $name ], $label );
- }
-
- /**
- * Constructs a table row with label and radio input in two columns.
- * @param string $name Option name.
- * @param FormOptions $opts
- * @param string[] $alts List of alternatives.
- * @return string Html.
- */
- protected function eRadio( $name, FormOptions $opts, array $alts ) {
- // Give grep a chance to find the usages:
- // translate-statsf-scale, translate-statsf-count
- $label = 'translate-statsf-' . $name;
- $label = $this->msg( $label )->escaped();
- $s = '<tr><td>' . $label . '</td><td>';
- $options = [];
- foreach ( $alts as $alt ) {
- $id = "$name-$alt";
- $radio = Xml::radio( $name, $alt, $alt === $opts[$name],
- [ 'id' => $id ] ) . ' ';
- $options[] = $radio . ' ' . $this->eLabel( $id );
- }
- $s .= implode( ' ', $options );
- $s .= '</td></tr>' . "\n";
- return $s;
- }
-
- /**
- * Constructs a table row with label and language selector in two columns.
- * @param string $name Option name.
- * @param FormOptions $opts
- * @return string Html.
- */
- protected function eLanguage( $name, FormOptions $opts ) {
- $value = implode( ',', $opts[$name] );
-
- $select = $this->languageSelector();
- $select->setTargetId( 'language' );
- return '<tr><td>' . $this->eLabel( $name ) . '</td><td>' .
- $select->getHtmlAndPrepareJS() . '<br />' .
- Xml::input( $name, 20, $value, [ 'id' => $name ] ) .
- '</td></tr>' . "\n";
- }
-
- /**
- * Constructs a JavaScript enhanced language selector.
- * @return JsSelectToInput
- */
- protected function languageSelector() {
- $languages = TranslateUtils::getLanguageNames( $this->getLanguage()->getCode() );
- ksort( $languages );
- $selector = new XmlSelect( 'mw-language-selector', 'mw-language-selector' );
- foreach ( $languages as $code => $name ) {
- $selector->addOption( "$code - $name", $code );
- }
- $jsSelect = new JsSelectToInput( $selector );
- return $jsSelect;
- }
-
- /**
- * Constructs a table row with label and group selector in two columns.
- * @param string $name Option name.
- * @param FormOptions $opts
- * @return string Html.
- */
- protected function eGroup( $name, FormOptions $opts ) {
- $value = implode( ',', $opts[$name] );
-
- $select = $this->groupSelector();
- $select->setTargetId( 'group' );
- return '<tr><td>' . $this->eLabel( $name ) . '</td><td>' .
- $select->getHtmlAndPrepareJS() . '<br />' .
- Xml::input( $name, 20, $value, [ 'id' => $name ] ) .
- '</td></tr>' . "\n";
- }
-
- /**
- * Constructs a JavaScript enhanced group selector.
- * @return JsSelectToInput
- */
- protected function groupSelector() {
- $groups = MessageGroups::singleton()->getGroups();
- /** @var MessageGroup $group */
- foreach ( $groups as $key => $group ) {
- if ( !$group->exists() ) {
- unset( $groups[$key] );
- continue;
- }
- }
- ksort( $groups );
- $selector = new XmlSelect( 'mw-group-selector', 'mw-group-selector' );
- /** @var MessageGroup $name */
- foreach ( $groups as $code => $name ) {
- $selector->addOption( $name->getLabel(), $code );
- }
- $jsSelect = new JsSelectToInput( $selector );
- return $jsSelect;
- }
-
- protected function embed( FormOptions $opts ) {
- $this->getOutput()->addModules( 'ext.translate.translationstats.embedded' );
- return Html::rawElement(
- 'div',
- [
- 'class' => self::GRAPH_CONTAINER_CLASS
- ],
- Html::hidden(
- 'translationStatsGraphOptions',
- json_encode( $opts->getAllValues() )
- )
- );
- }
-}
diff --git a/MLEB/Translate/specials/SpecialTranslations.php b/MLEB/Translate/specials/SpecialTranslations.php
index ebdf1787..87632a2f 100644
--- a/MLEB/Translate/specials/SpecialTranslations.php
+++ b/MLEB/Translate/specials/SpecialTranslations.php
@@ -167,10 +167,7 @@ class SpecialTranslations extends SpecialAllPages {
'page_title ' . $dbr->buildLike( "$message/", $dbr->anyString() ),
],
__METHOD__,
- [
- 'ORDER BY' => 'page_title',
- 'USE INDEX' => 'name_title',
- ]
+ [ 'ORDER BY' => 'page_title', ]
);
if ( !$res->numRows() ) {
@@ -246,7 +243,7 @@ class SpecialTranslations extends SpecialAllPages {
$languageAttributes = [];
if ( Language::isKnownLanguageTag( $code ) ) {
- $language = Language::factory( $code );
+ $language = $tHandle->getEffectiveLanguage();
$languageAttributes = [
'lang' => $language->getHtmlCode(),
'dir' => $language->getDir(),