summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'MLEB/Translate/utils')
-rw-r--r--MLEB/Translate/utils/ArrayFlattener.php1
-rw-r--r--MLEB/Translate/utils/ExternalMessageSourceStateComparator.php21
-rw-r--r--MLEB/Translate/utils/ExternalMessageSourceStateImporter.php145
-rw-r--r--MLEB/Translate/utils/FCFontFinder.php138
-rw-r--r--MLEB/Translate/utils/HTMLJsSelectToInputField.php4
-rw-r--r--MLEB/Translate/utils/JsSelectToInput.php23
-rw-r--r--MLEB/Translate/utils/MemProfile.php63
-rw-r--r--MLEB/Translate/utils/MessageChangeStorage.php6
-rw-r--r--MLEB/Translate/utils/MessageGroupCache.php24
-rw-r--r--MLEB/Translate/utils/MessageGroupStatesUpdaterJob.php11
-rw-r--r--MLEB/Translate/utils/MessageGroupStats.php28
-rw-r--r--MLEB/Translate/utils/MessageGroupStatsRebuildJob.php10
-rw-r--r--MLEB/Translate/utils/MessageGroupWANCache.php11
-rw-r--r--MLEB/Translate/utils/MessageHandle.php26
-rw-r--r--MLEB/Translate/utils/MessageIndex.php58
-rw-r--r--MLEB/Translate/utils/MessageIndexException.php4
-rw-r--r--MLEB/Translate/utils/MessageIndexRebuildJob.php6
-rw-r--r--MLEB/Translate/utils/MessageUpdateJob.php101
-rw-r--r--MLEB/Translate/utils/MessageWebImporter.php73
-rw-r--r--MLEB/Translate/utils/StatsBar.php10
-rw-r--r--MLEB/Translate/utils/StatsTable.php67
-rw-r--r--MLEB/Translate/utils/TranslateLogFormatter.php7
-rw-r--r--MLEB/Translate/utils/TranslateMetadata.php12
-rw-r--r--MLEB/Translate/utils/TranslateSandbox.php65
-rw-r--r--MLEB/Translate/utils/TranslateSandboxEmailJob.php13
-rw-r--r--MLEB/Translate/utils/TranslateToolbox.php2
-rw-r--r--MLEB/Translate/utils/TranslationHelpers.php196
27 files changed, 397 insertions, 728 deletions
diff --git a/MLEB/Translate/utils/ArrayFlattener.php b/MLEB/Translate/utils/ArrayFlattener.php
index db57b4f5..5e8d91bc 100644
--- a/MLEB/Translate/utils/ArrayFlattener.php
+++ b/MLEB/Translate/utils/ArrayFlattener.php
@@ -14,7 +14,6 @@
class ArrayFlattener {
protected $sep;
protected $parseCLDRPlurals;
-
// For CLDR pluralization rules
protected static $pluralWords = [
'zero' => 1,
diff --git a/MLEB/Translate/utils/ExternalMessageSourceStateComparator.php b/MLEB/Translate/utils/ExternalMessageSourceStateComparator.php
index a6b53f4f..9b4b298d 100644
--- a/MLEB/Translate/utils/ExternalMessageSourceStateComparator.php
+++ b/MLEB/Translate/utils/ExternalMessageSourceStateComparator.php
@@ -8,21 +8,17 @@
* @since 2013.12
*/
-use MediaWiki\Extensions\Translate\MessageSync\MessageSourceChange;
-use MediaWiki\Extensions\Translate\Utilities\StringComparators\StringComparator;
+use MediaWiki\Extension\Translate\MessageSync\MessageSourceChange;
+use MediaWiki\Extension\Translate\Utilities\StringComparators\StringComparator;
class ExternalMessageSourceStateComparator {
/** Process all languages supported by the message group */
public const ALL_LANGUAGES = 'all languages';
- /**
- * @var StringComparator
- */
+ /** @var StringComparator */
protected $stringComparator;
- /**
- * @param StringComparator $stringComparator
- */
+ /** @param StringComparator $stringComparator */
public function __construct( StringComparator $stringComparator ) {
$this->stringComparator = $stringComparator;
}
@@ -129,9 +125,8 @@ class ExternalMessageSourceStateComparator {
) {
/* This throws a warning if message definitions are not yet
* cached and will read the file for definitions. */
- Wikimedia\suppressWarnings();
- $wiki = $group->initCollection( $language );
- Wikimedia\restoreWarnings();
+ // phpcs:disable Generic.PHP.NoSilencedErrors.Discouraged
+ $wiki = @$group->initCollection( $language );
$wiki->filter( 'hastranslation', false );
$wiki->loadTranslations();
$wikiKeys = $wiki->getMessageKeys();
@@ -233,10 +228,6 @@ class ExternalMessageSourceStateComparator {
$added = array_diff( $fileKeys, $wikiKeys );
foreach ( $added as $key ) {
$sourceContent = $file['MESSAGES'][$key];
- if ( trim( $sourceContent ) === '' ) {
- continue;
- }
-
$changes->addAddition( $language, $key, $sourceContent );
}
diff --git a/MLEB/Translate/utils/ExternalMessageSourceStateImporter.php b/MLEB/Translate/utils/ExternalMessageSourceStateImporter.php
index 51674921..5fa3f471 100644
--- a/MLEB/Translate/utils/ExternalMessageSourceStateImporter.php
+++ b/MLEB/Translate/utils/ExternalMessageSourceStateImporter.php
@@ -8,7 +8,10 @@
* @since 2016.02
*/
-use MediaWiki\Extensions\Translate\MessageSync\MessageSourceChange;
+use MediaWiki\Extension\Translate\MessageSync\MessageSourceChange;
+use MediaWiki\Extension\Translate\Services;
+use MediaWiki\Extension\Translate\Synchronization\MessageUpdateParameter;
+use MediaWiki\MediaWikiServices;
class ExternalMessageSourceStateImporter {
@@ -22,13 +25,9 @@ class ExternalMessageSourceStateImporter {
$jobs = [];
$jobs[] = MessageIndexRebuildJob::newJob();
- /**
- * @var MessageSourceChange $changesForGroup
- */
+ /** @var MessageSourceChange $changesForGroup */
foreach ( $changeData as $groupId => $changesForGroup ) {
- /**
- * @var FileBasedMessageGroup
- */
+ /** @var FileBasedMessageGroup */
$group = MessageGroups::getGroup( $groupId );
if ( !$group ) {
unset( $changeData[$groupId] );
@@ -38,10 +37,12 @@ class ExternalMessageSourceStateImporter {
$processed[$groupId] = [];
$languages = $changesForGroup->getLanguages();
+ $groupJobs = [];
+
+ $groupSafeLanguages = self::identifySafeLanguages( $group, $changesForGroup );
foreach ( $languages as $language ) {
- if ( !self::isSafe( $changesForGroup, $language ) ) {
- // changes other than additions were present
+ if ( !$groupSafeLanguages[ $language ] ) {
$skipped[$groupId] = true;
continue;
}
@@ -51,16 +52,21 @@ class ExternalMessageSourceStateImporter {
continue;
}
- [ $groupJobs, $groupProcessed ] = $this->createMessageUpdateJobs(
+ [ $groupLanguageJobs, $groupProcessed ] = $this->createMessageUpdateJobs(
$group, $additions, $language
);
- $jobs = array_merge( $jobs, $groupJobs );
+ $groupJobs = array_merge( $groupJobs, $groupLanguageJobs );
$processed[$groupId][$language] = $groupProcessed;
$changesForGroup->removeChangesForLanguage( $language );
$group->getMessageGroupCache( $language )->create();
}
+
+ if ( $groupJobs !== [] ) {
+ $this->updateGroupSyncInfo( $groupId, $groupJobs );
+ $jobs = array_merge( $jobs, $groupJobs );
+ }
}
// Remove groups where everything was imported
@@ -84,16 +90,6 @@ class ExternalMessageSourceStateImporter {
}
/**
- * Checks if changes for a language in a group are safe.
- * @param MessageSourceChange $changesForGroup
- * @param string $language
- * @return bool
- */
- public static function isSafe( MessageSourceChange $changesForGroup, $language ) {
- return $changesForGroup->hasOnly( $language, MessageSourceChange::ADDITION );
- }
-
- /**
* Creates MessagUpdateJobs additions for a language under a group
*
* @param MessageGroup $group
@@ -123,4 +119,111 @@ class ExternalMessageSourceStateImporter {
return [ $jobs, $processed ];
}
+
+ /**
+ * @param string $groupId
+ * @param MessageUpdateJob[] $groupJobs
+ */
+ private function updateGroupSyncInfo( string $groupId, array $groupJobs ): void {
+ $config = MediaWikiServices::getInstance()->getMainConfig();
+
+ if ( !$config->get( 'TranslateGroupSynchronizationCache' ) ) {
+ return;
+ }
+
+ $messageParams = [];
+ $groupMessageKeys = [];
+ foreach ( $groupJobs as $job ) {
+ $messageParams[] = MessageUpdateParameter::createFromJob( $job );
+ // Ensure there are no duplicates as the same key may be present in
+ // multiple languages
+ $groupMessageKeys[( new MessageHandle( $job->getTitle() ) )->getKey()] = true;
+ }
+
+ $group = MessageGroups::getGroup( $groupId );
+ if ( $group === null ) {
+ // How did we get here? This should never happen.
+ throw new RuntimeException( "Did not find group $groupId" );
+ }
+
+ MessageIndex::singleton()->storeInterim( $group, array_keys( $groupMessageKeys ) );
+
+ $groupSyncCache = Services::getInstance()->getGroupSynchronizationCache();
+ $groupSyncCache->addMessages( $groupId, ...$messageParams );
+ $groupSyncCache->markGroupForSync( $groupId );
+ }
+
+ /**
+ * Identifies languages in a message group that are safe to import
+ * @param MessageGroup $group
+ * @param MessageSourceChange $changesForGroup
+ * @return bool[]
+ */
+ private static function identifySafeLanguages(
+ MessageGroup $group,
+ MessageSourceChange $changesForGroup
+ ): array {
+ $sourceLanguage = $group->getSourceLanguage();
+ $safeLanguagesMap = [];
+ $modifiedLanguages = $changesForGroup->getLanguages();
+
+ // Set all languages to not safe to start with.
+ $safeLanguagesMap[ $sourceLanguage ] = false;
+ foreach ( $modifiedLanguages as $language ) {
+ $safeLanguagesMap[ $language ] = false;
+ }
+
+ if ( !$changesForGroup->hasOnly( $sourceLanguage, MessageSourceChange::ADDITION ) ) {
+ return $safeLanguagesMap;
+ }
+
+ $sourceLanguageKeyCache = [];
+ foreach ( $changesForGroup->getAdditions( $sourceLanguage ) as $change ) {
+ if ( $change['content'] === '' ) {
+ return $safeLanguagesMap;
+ }
+
+ $sourceLanguageKeyCache[ $change['key'] ] = true;
+ }
+
+ $safeLanguagesMap[ $sourceLanguage ] = true;
+
+ $groupNamespace = $group->getNamespace();
+
+ // Remove source language from the modifiedLanguage list if present since it's already processed.
+ // The $sourceLanguageKeyCache will only have values if sourceLanguage has safe changes.
+ if ( $sourceLanguageKeyCache ) {
+ array_splice( $modifiedLanguages, array_search( $sourceLanguage, $modifiedLanguages ), 1 );
+ }
+
+ foreach ( $modifiedLanguages as $language ) {
+ if ( !$changesForGroup->hasOnly( $language, MessageSourceChange::ADDITION ) ) {
+ continue;
+ }
+
+ foreach ( $changesForGroup->getAdditions( $language ) as $change ) {
+ if ( $change['content'] === '' ) {
+ continue 2;
+ }
+
+ $msgKey = $change['key'];
+
+ if ( !isset( $sourceLanguageKeyCache[ $msgKey ] ) ) {
+ // This is either a new external translation which is not added in the same sync
+ // as the source language key, or this translation does not have a correspoding
+ // definition. We will check the message index to determine which of the two.
+ $sourceHandle = new MessageHandle( Title::makeTitle( $groupNamespace, $msgKey ) );
+ $sourceLanguageKeyCache[ $msgKey ] = $sourceHandle->isValid();
+ }
+
+ if ( !$sourceLanguageKeyCache[ $msgKey ] ) {
+ continue 2;
+ }
+ }
+
+ $safeLanguagesMap[ $language ] = true;
+ }
+
+ return $safeLanguagesMap;
+ }
}
diff --git a/MLEB/Translate/utils/FCFontFinder.php b/MLEB/Translate/utils/FCFontFinder.php
deleted file mode 100644
index 37fa4ac7..00000000
--- a/MLEB/Translate/utils/FCFontFinder.php
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-/**
- * Contains class with wrapper around font-config.
- *
- * @author Niklas Laxström
- * @author Harry Burt
- * @license Unlicense
- * @file
- */
-
-/**
- * Wrapper around font-config to get useful ttf font given a language code.
- * Uses wfShellExec, wfEscapeShellArg and wfDebugLog, wfGetCache and
- * wfMemckey from %MediaWiki.
- *
- * @ingroup Stats
- */
-class FCFontFinder {
- /**
- * Searches for suitable font in the system.
- * @param string $code Language code.
- * @return bool|string Full path to the font file, false on failure
- */
- public static function findFile( $code ) {
- $data = self::callFontConfig( $code );
- if ( is_array( $data ) ) {
- return $data['file'];
- }
-
- return false;
- }
-
- /**
- * Searches for suitable font family in the system.
- * @param string $code Language code.
- * @return bool|string Name of font family, false on failure
- */
- public static function findFamily( $code ) {
- $data = self::callFontConfig( $code );
- if ( is_array( $data ) ) {
- return $data['family'];
- }
-
- return false;
- }
-
- protected static function callFontConfig( $code ) {
- if ( ini_get( 'open_basedir' ) ) {
- wfDebugLog( 'fcfont', 'Disabled because of open_basedir is active' );
-
- // Most likely we can't access any fonts we might find
- return false;
- }
-
- $cache = self::getCache();
- $cachekey = wfMemcKey( 'fcfont', $code );
- $timeout = 60 * 60 * 12;
-
- $cached = $cache->get( $cachekey );
- if ( is_array( $cached ) ) {
- return $cached;
- } elseif ( $cached === 'NEGATIVE' ) {
- return false;
- }
-
- $code = wfEscapeShellArg( ":lang=$code" );
- $ok = 0;
- $cmd = "fc-match $code";
- $suggestion = wfShellExec( $cmd, $ok );
-
- wfDebugLog( 'fcfont', "$cmd returned $ok" );
-
- if ( $ok !== 0 ) {
- wfDebugLog( 'fcfont', "fc-match error output: $suggestion" );
- $cache->set( $cachekey, 'NEGATIVE', $timeout );
-
- return false;
- }
-
- $pattern = '/^(.*?): "(.*)" "(.*)"$/';
- $matches = [];
-
- if ( !preg_match( $pattern, $suggestion, $matches ) ) {
- wfDebugLog( 'fcfont', "fc-match: return format not understood: $suggestion" );
- $cache->set( $cachekey, 'NEGATIVE', $timeout );
-
- return false;
- }
-
- list( , $file, $family, $type ) = $matches;
- wfDebugLog( 'fcfont', "fc-match: got $file: $family $type" );
-
- $file = wfEscapeShellArg( $file );
- $family = wfEscapeShellArg( $family );
- $type = wfEscapeShellArg( $type );
- $cmd = "fc-list $family $type $code file | grep $file";
-
- $candidates = trim( wfShellExec( $cmd, $ok ) );
-
- wfDebugLog( 'fcfont', "$cmd returned $ok" );
-
- if ( $ok !== 0 ) {
- wfDebugLog( 'fcfont', "fc-list error output: $candidates" );
- $cache->set( $cachekey, 'NEGATIVE', $timeout );
-
- return false;
- }
-
- # trim spaces
- $files = array_map( 'trim', explode( "\n", $candidates ) );
- $count = count( $files );
- if ( !$count ) {
- wfDebugLog( 'fcfont', "fc-list got zero canditates: $candidates" );
- }
-
- # remove the trailing ":"
- $chosen = substr( $files[0], 0, -1 );
-
- wfDebugLog( 'fcfont', "fc-list got $count candidates; using $chosen" );
-
- $data = [
- 'family' => $family,
- 'type' => $type,
- 'file' => $chosen,
- ];
-
- $cache->set( $cachekey, $data, $timeout );
-
- return $data;
- }
-
- /**
- * @return BagOStuff
- */
- protected static function getCache() {
- return wfGetCache( CACHE_ANYTHING );
- }
-}
diff --git a/MLEB/Translate/utils/HTMLJsSelectToInputField.php b/MLEB/Translate/utils/HTMLJsSelectToInputField.php
index 57f4443c..d3b22472 100644
--- a/MLEB/Translate/utils/HTMLJsSelectToInputField.php
+++ b/MLEB/Translate/utils/HTMLJsSelectToInputField.php
@@ -19,9 +19,7 @@ class HTMLJsSelectToInputField extends HTMLTextField {
$input = parent::getInputHTML( $value );
if ( isset( $this->mParams['select'] ) ) {
- /**
- * @var JsSelectToInput $select
- */
+ /** @var JsSelectToInput $select */
$select = $this->mParams['select'];
$input = $select->getHtmlAndPrepareJS() . '<br />' . $input;
}
diff --git a/MLEB/Translate/utils/JsSelectToInput.php b/MLEB/Translate/utils/JsSelectToInput.php
index 83d5cc65..188b5e0f 100644
--- a/MLEB/Translate/utils/JsSelectToInput.php
+++ b/MLEB/Translate/utils/JsSelectToInput.php
@@ -15,27 +15,18 @@ class JsSelectToInput {
protected $targetId;
/// Id of the \<option> field
protected $sourceId;
-
- /**
- * @var XmlSelect
- */
+ /** @var XmlSelect */
protected $select;
-
/// Id on the button
protected $buttonId;
-
- /**
- * @var string Text for the append button
- */
+ /** @var string Text for the append button */
protected $msg = 'translate-jssti-add';
public function __construct( XmlSelect $select = null ) {
$this->select = $select;
}
- /**
- * @return string
- */
+ /** @return string */
public function getSourceId() {
return $this->sourceId;
}
@@ -48,9 +39,7 @@ class JsSelectToInput {
$this->targetId = $id;
}
- /**
- * @return string
- */
+ /** @return string */
public function getTargetId() {
return $this->targetId;
}
@@ -63,9 +52,7 @@ class JsSelectToInput {
$this->msg = $message;
}
- /**
- * @return string Message key.
- */
+ /** @return string Message key. */
public function getMessage() {
return $this->msg;
}
diff --git a/MLEB/Translate/utils/MemProfile.php b/MLEB/Translate/utils/MemProfile.php
deleted file mode 100644
index 7ebc3423..00000000
--- a/MLEB/Translate/utils/MemProfile.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-if ( !defined( 'MEDIAWIKI' ) ) {
- die();
-}
-/**
- * Very crude tools to track memory usage
- *
- * @file
- * @author Niklas Laxström
- * @copyright Copyright © 2008, Niklas Laxström
- * @license GPL-2.0-or-later
- */
-
-/// Memory usage at checkpoints
-$wgMemUse = [];
-/// Tracks the deepness of the stack
-$wgMemStack = 0;
-
-/**
- * Call to start memory counting for a block.
- * @param string $a Block name.
- */
-function wfMemIn( $a ) {
- global $wgLang, $wgMemUse, $wgMemStack;
-
- $mem = memory_get_usage();
- $memR = memory_get_usage();
-
- $wgMemUse[$a][] = [ $mem, $memR ];
-
- $memF = $wgLang->formatNum( $mem );
- $memRF = $wgLang->formatNum( $memR );
-
- $pad = str_repeat( '.', $wgMemStack );
- wfDebug( "$pad$a-IN: \t$memF\t\t$memRF\n" );
- $wgMemStack++;
-}
-
-/**
- * Call to start stop counting for a block. Difference from start is shown.
- * @param string $a Block name.
- */
-function wfMemOut( $a ) {
- global $wgLang, $wgMemUse, $wgMemStack;
-
- $mem = memory_get_usage();
- $memR = memory_get_usage();
-
- list( $memO, $memOR ) = array_pop( $wgMemUse[$a] );
-
- $memF = $wgLang->formatNum( $mem );
- $memRF = $wgLang->formatNum( $memR );
-
- $memD = $mem - $memO;
- $memRD = $memR - $memOR;
-
- $memDF = $wgLang->formatNum( $memD );
- $memRDF = $wgLang->formatNum( $memRD );
-
- $pad = str_repeat( '.', $wgMemStack - 1 );
- wfDebug( "$pad$a-OUT:\t$memF ($memDF)\t$memRF ($memRDF)\n" );
- $wgMemStack--;
-}
diff --git a/MLEB/Translate/utils/MessageChangeStorage.php b/MLEB/Translate/utils/MessageChangeStorage.php
index 6fbd8a0a..b53f966c 100644
--- a/MLEB/Translate/utils/MessageChangeStorage.php
+++ b/MLEB/Translate/utils/MessageChangeStorage.php
@@ -8,7 +8,7 @@
* @file
*/
-use MediaWiki\Extensions\Translate\MessageSync\MessageSourceChange;
+use MediaWiki\Extension\Translate\MessageSync\MessageSourceChange;
class MessageChangeStorage {
public const DEFAULT_NAME = 'default';
@@ -25,9 +25,7 @@ class MessageChangeStorage {
$keys = array_keys( $changes );
$cache->set( '#keys', TranslateUtils::serialize( $keys ) );
- /**
- * @var MessageSourceChange $change
- */
+ /** @var MessageSourceChange $change */
foreach ( $changes as $key => $change ) {
$value = TranslateUtils::serialize( $change->getAllModifications() );
$cache->set( $key, $value );
diff --git a/MLEB/Translate/utils/MessageGroupCache.php b/MLEB/Translate/utils/MessageGroupCache.php
index fdb1fc01..fa174a35 100644
--- a/MLEB/Translate/utils/MessageGroupCache.php
+++ b/MLEB/Translate/utils/MessageGroupCache.php
@@ -19,24 +19,13 @@ class MessageGroupCache {
public const NO_CACHE = 2;
public const CHANGED = 3;
- /**
- * @var FileBasedMessageGroup
- */
+ /** @var FileBasedMessageGroup */
protected $group;
-
- /**
- * @var \Cdb\Reader
- */
+ /** @var \Cdb\Reader */
protected $cache;
-
- /**
- * @var string
- */
+ /** @var string */
protected $code;
-
- /**
- * @var string
- */
+ /** @var string */
private $cacheFilePath;
/**
@@ -253,6 +242,11 @@ class MessageGroupCache {
return false;
}
+ public function invalidate(): void {
+ $this->close();
+ unlink( $this->getCacheFilePath() );
+ }
+
private function serialize( array $data ): string {
// Using simple prefix for easy future extension
return 'J' . json_encode( $data );
diff --git a/MLEB/Translate/utils/MessageGroupStatesUpdaterJob.php b/MLEB/Translate/utils/MessageGroupStatesUpdaterJob.php
index dda4a8f9..c261106e 100644
--- a/MLEB/Translate/utils/MessageGroupStatesUpdaterJob.php
+++ b/MLEB/Translate/utils/MessageGroupStatesUpdaterJob.php
@@ -8,14 +8,16 @@
* @license GPL-2.0-or-later
*/
-use MediaWiki\Extensions\Translate\SystemUsers\FuzzyBot;
+use MediaWiki\Extension\Translate\Jobs\GenericTranslateJob;
+use MediaWiki\Extension\Translate\SystemUsers\FuzzyBot;
+use MediaWiki\MediaWikiServices;
/**
* Logic for handling automatic message group state changes
*
* @ingroup JobQueue
*/
-class MessageGroupStatesUpdaterJob extends Job {
+class MessageGroupStatesUpdaterJob extends GenericTranslateJob {
/**
* @param Title $title
* @param array $params
@@ -49,6 +51,11 @@ class MessageGroupStatesUpdaterJob extends Job {
}
public function run() {
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ if ( !$lb->waitForReplication() ) {
+ $this->logWarning( 'Continuing despite replication lag' );
+ }
+
$title = $this->title;
$handle = new MessageHandle( $title );
$code = $handle->getCode();
diff --git a/MLEB/Translate/utils/MessageGroupStats.php b/MLEB/Translate/utils/MessageGroupStats.php
index 91267f22..dc7b1133 100644
--- a/MLEB/Translate/utils/MessageGroupStats.php
+++ b/MLEB/Translate/utils/MessageGroupStats.php
@@ -8,6 +8,7 @@
* @license GPL-2.0-or-later
*/
+use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
use Wikimedia\Rdbms\IDatabase;
@@ -34,14 +35,9 @@ class MessageGroupStats {
/// Do not defer updates. Meant for jobs like MessageGroupStatsRebuildJob.
public const FLAG_IMMEDIATE_WRITES = 4;
- /**
- * @var array[]
- */
+ /** @var array[] */
protected static $updates = [];
-
- /**
- * @var string[]
- */
+ /** @var string[] */
private static $languages;
/**
@@ -547,9 +543,7 @@ class MessageGroupStats {
if ( $code === $wgTranslateDocumentationLanguageCode ) {
$ffs = $group->getFFS();
if ( $ffs instanceof GettextFFS ) {
- /**
- * @var FileBasedMessageGroup $group
- */
+ /** @var FileBasedMessageGroup $group */
'@phan-var FileBasedMessageGroup $group';
$cache = $group->getMessageGroupCache( $group->getSourceLanguage() );
if ( $cache->exists() ) {
@@ -566,7 +560,7 @@ class MessageGroupStats {
}
$collection->filter( 'ignored' );
- $collection->filter( 'optional' );
+ $collection->filterUntranslatedOptional();
// Store the count of real messages for later calculation.
$total = count( $collection );
@@ -626,6 +620,18 @@ class MessageGroupStats {
return;
}
+ // This path should only be hit during web requests
+ if ( count( $updates ) > 100 ) {
+ $groups = array_unique( array_column( $updates, 'tgs_group' ) );
+ LoggerFactory::getInstance( 'Translate' )->warning(
+ "Huge translation update of {count} rows for group(s) {groups}",
+ [
+ 'count' => count( $updates ),
+ 'groups' => implode( ', ', $groups ),
+ ]
+ );
+ }
+
$primaryKey = [ 'tgs_group', 'tgs_lang' ];
$dbw->replace( $table, [ $primaryKey ], $updates, $method );
$updates = [];
diff --git a/MLEB/Translate/utils/MessageGroupStatsRebuildJob.php b/MLEB/Translate/utils/MessageGroupStatsRebuildJob.php
index e813d614..53c3a496 100644
--- a/MLEB/Translate/utils/MessageGroupStatsRebuildJob.php
+++ b/MLEB/Translate/utils/MessageGroupStatsRebuildJob.php
@@ -7,12 +7,15 @@
* @license GPL-2.0-or-later
*/
+use MediaWiki\Extension\Translate\Jobs\GenericTranslateJob;
+use MediaWiki\MediaWikiServices;
+
/**
* Job for rebuilding message group stats.
*
* @ingroup JobQueue
*/
-class MessageGroupStatsRebuildJob extends Job {
+class MessageGroupStatsRebuildJob extends GenericTranslateJob {
/**
* @param array $params
* @return self
@@ -45,6 +48,11 @@ class MessageGroupStatsRebuildJob extends Job {
}
public function run() {
+ $lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ if ( !$lb->waitForReplication() ) {
+ $this->logWarning( 'Continuing despite replication lag' );
+ }
+
$params = $this->params;
$flags = 0;
diff --git a/MLEB/Translate/utils/MessageGroupWANCache.php b/MLEB/Translate/utils/MessageGroupWANCache.php
index 4df5b4c7..78d8e817 100644
--- a/MLEB/Translate/utils/MessageGroupWANCache.php
+++ b/MLEB/Translate/utils/MessageGroupWANCache.php
@@ -14,50 +14,41 @@
*/
class MessageGroupWANCache {
- /**
- * @var WANObjectCache
- */
+ /** @var WANObjectCache */
protected $cache;
-
/**
* Cache key
*
* @var string
*/
protected $cacheKey;
-
/**
* Cache version
*
* @var int
*/
protected $cacheVersion;
-
/**
* To be called when the cache is empty or expired to get the data
* to repopulate the cache
* @var \Closure
*/
protected $regenerator;
-
/**
* @see @https://doc.wikimedia.org/mediawiki-core/master/php/classWANObjectCache.html
* @var int
*/
protected $lockTSE;
-
/**
* @see @https://doc.wikimedia.org/mediawiki-core/master/php/classWANObjectCache.html
* @var array
*/
protected $checkKeys;
-
/**
* @see @https://doc.wikimedia.org/mediawiki-core/master/php/classWANObjectCache.html
* @var \Closure
*/
protected $touchedCallback;
-
/**
* @see @https://doc.wikimedia.org/mediawiki-core/master/php/classWANObjectCache.html
* @var int
diff --git a/MLEB/Translate/utils/MessageHandle.php b/MLEB/Translate/utils/MessageHandle.php
index bb9c43c5..3d95608f 100644
--- a/MLEB/Translate/utils/MessageHandle.php
+++ b/MLEB/Translate/utils/MessageHandle.php
@@ -16,24 +16,13 @@ use MediaWiki\MediaWikiServices;
* @since 2011-03-13
*/
class MessageHandle {
- /**
- * @var LinkTarget
- */
+ /** @var LinkTarget */
protected $title;
-
- /**
- * @var string|null
- */
+ /** @var string|null */
protected $key;
-
- /**
- * @var string|null Language code
- */
+ /** @var string|null Language code */
protected $code;
-
- /**
- * @var string[]|null
- */
+ /** @var string[]|null */
protected $groupIds;
public function __construct( LinkTarget $title ) {
@@ -76,7 +65,7 @@ class MessageHandle {
/**
* Returns the identified or guessed message key.
- * @return String
+ * @return string
*/
public function getKey() {
$this->figureMessage();
@@ -87,7 +76,7 @@ class MessageHandle {
/**
* Returns the language code.
* For language codeless source messages will return empty string.
- * @return String
+ * @return string
*/
public function getCode() {
$this->figureMessage();
@@ -272,7 +261,8 @@ class MessageHandle {
public function getInternalKey() {
$key = $this->getKey();
- if ( !MWNamespace::isCapitalized( $this->title->getNamespace() ) ) {
+ $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+ if ( !$nsInfo->isCapitalized( $this->title->getNamespace() ) ) {
return $key;
}
diff --git a/MLEB/Translate/utils/MessageIndex.php b/MLEB/Translate/utils/MessageIndex.php
index 128efe85..1cbdaf39 100644
--- a/MLEB/Translate/utils/MessageIndex.php
+++ b/MLEB/Translate/utils/MessageIndex.php
@@ -21,22 +21,14 @@ use MediaWiki\Logger\LoggerFactory;
abstract class MessageIndex {
private const CACHEKEY = 'Translate-MessageIndex-interim';
- /**
- * @var self
- */
+ /** @var self */
protected static $instance;
-
- /**
- * @var MapCacheLRU|null
- */
+ /** @var MapCacheLRU|null */
private static $keysCache;
-
/** @var BagOStuff */
protected $interimCache;
- /**
- * @return self
- */
+ /** @return self */
public static function singleton() {
if ( self::$instance === null ) {
global $wgTranslateMessageIndex;
@@ -91,9 +83,7 @@ abstract class MessageIndex {
return $value;
}
- /**
- * @return MapCacheLRU
- */
+ /** @return MapCacheLRU */
private static function getCache() {
if ( self::$keysCache === null ) {
self::$keysCache = new MapCacheLRU( 30 );
@@ -202,9 +192,7 @@ abstract class MessageIndex {
$old = $this->retrieve( 'rebuild' );
$postponed = [];
- /**
- * @var MessageGroup $g
- */
+ /** @var MessageGroup $g */
foreach ( $groups as $g ) {
if ( !$g->exists() ) {
$id = $g->getId();
@@ -451,11 +439,8 @@ abstract class MessageIndex {
* which provides random access - this backend doesn't support that.
*/
class SerializedMessageIndex extends MessageIndex {
- /**
- * @var array|null
- */
+ /** @var array|null */
protected $index;
-
protected $filename = 'translate_messageindex.ser';
/**
@@ -496,9 +481,7 @@ class SerializedMessageIndex extends MessageIndex {
* @since 2012-04-12
*/
class DatabaseMessageIndex extends MessageIndex {
- /**
- * @var array|null
- */
+ /** @var array|null */
protected $index;
protected function lock() {
@@ -618,10 +601,7 @@ class DatabaseMessageIndex extends MessageIndex {
class CachedMessageIndex extends MessageIndex {
protected $key = 'translate-messageindex';
protected $cache;
-
- /**
- * @var array|null
- */
+ /** @var array|null */
protected $index;
protected function __construct() {
@@ -637,7 +617,7 @@ class CachedMessageIndex extends MessageIndex {
return $this->index;
}
- $key = wfMemcKey( $this->key );
+ $key = $this->cache->makeKey( $this->key );
$data = $this->cache->get( $key );
if ( is_array( $data ) ) {
$this->index = $data;
@@ -649,7 +629,7 @@ class CachedMessageIndex extends MessageIndex {
}
protected function store( array $array, array $diff ) {
- $key = wfMemcKey( $this->key );
+ $key = $this->cache->makeKey( $this->key );
$this->cache->set( $key, $array );
$this->index = $array;
@@ -670,19 +650,11 @@ class CachedMessageIndex extends MessageIndex {
* @since 2012-04-10
*/
class CDBMessageIndex extends MessageIndex {
- /**
- * @var array|null
- */
+ /** @var array|null */
protected $index;
-
- /**
- * @var \Cdb\Reader|null
- */
+ /** @var \Cdb\Reader|null */
protected $reader;
-
- /**
- * @var string
- */
+ /** @var string */
protected $filename = 'translate_messageindex.cdb';
/**
@@ -776,9 +748,7 @@ class CDBMessageIndex extends MessageIndex {
* @since 2015.04
*/
class HashMessageIndex extends MessageIndex {
- /**
- * @var array
- */
+ /** @var array */
protected $index = [];
/**
diff --git a/MLEB/Translate/utils/MessageIndexException.php b/MLEB/Translate/utils/MessageIndexException.php
index b0e5c7a6..77916d1c 100644
--- a/MLEB/Translate/utils/MessageIndexException.php
+++ b/MLEB/Translate/utils/MessageIndexException.php
@@ -5,8 +5,6 @@
* @license GPL-2.0-or-later
*/
-/**
- * @since 2020.05
- */
+/** @since 2020.05 */
class MessageIndexException extends RuntimeException {
}
diff --git a/MLEB/Translate/utils/MessageIndexRebuildJob.php b/MLEB/Translate/utils/MessageIndexRebuildJob.php
index abcb7b91..a155ff9e 100644
--- a/MLEB/Translate/utils/MessageIndexRebuildJob.php
+++ b/MLEB/Translate/utils/MessageIndexRebuildJob.php
@@ -8,7 +8,7 @@
* @license GPL-2.0-or-later
*/
-use MediaWiki\Extensions\Translate\Jobs\GenericTranslateJob;
+use MediaWiki\Extension\Translate\Jobs\GenericTranslateJob;
/**
* Job for rebuilding message index.
@@ -16,9 +16,7 @@ use MediaWiki\Extensions\Translate\Jobs\GenericTranslateJob;
* @ingroup JobQueue
*/
class MessageIndexRebuildJob extends GenericTranslateJob {
- /**
- * @return self
- */
+ /** @return self */
public static function newJob() {
$timestamp = microtime( true );
$job = new self( Title::newMainPage(), [ 'timestamp' => $timestamp ] );
diff --git a/MLEB/Translate/utils/MessageUpdateJob.php b/MLEB/Translate/utils/MessageUpdateJob.php
index 8d4ff35a..7ad7b998 100644
--- a/MLEB/Translate/utils/MessageUpdateJob.php
+++ b/MLEB/Translate/utils/MessageUpdateJob.php
@@ -8,9 +8,11 @@
* @license GPL-2.0-or-later
*/
-use MediaWiki\Extensions\Translate\Jobs\GenericTranslateJob;
-use MediaWiki\Extensions\Translate\SystemUsers\FuzzyBot;
-use MediaWiki\Extensions\Translate\Utilities\TranslateReplaceTitle;
+use MediaWiki\Extension\Translate\Jobs\GenericTranslateJob;
+use MediaWiki\Extension\Translate\Services;
+use MediaWiki\Extension\Translate\SystemUsers\FuzzyBot;
+use MediaWiki\Extension\Translate\Utilities\TranslateReplaceTitle;
+use MediaWiki\MediaWikiServices;
/**
* Job for updating translation pages when translation or message definition changes.
@@ -22,10 +24,12 @@ class MessageUpdateJob extends GenericTranslateJob {
* Create a normal message update job without a rename process
* @param Title $target
* @param string $content
- * @param bool $fuzzy
- * @return MessageUpdateJob
+ * @param string|false $fuzzy
+ * @return self
*/
- public static function newJob( Title $target, $content, $fuzzy = false ) {
+ public static function newJob(
+ Title $target, string $content, $fuzzy = false
+ ): self {
$params = [
'content' => $content,
'fuzzy' => $fuzzy,
@@ -38,17 +42,22 @@ class MessageUpdateJob extends GenericTranslateJob {
/**
* Create a message update job containing a rename process
- * @param Title $target Target message being modified
- * @param string $targetStr Target string
- * @param string $replacement Replacement string
- * @param bool $fuzzy Whether to fuzzy the message
- * @param string $content Content of the source language
- * @param array $otherLangContents Content to be updated for other languages
- * @return MessageUpdateJob
+ * @param Title $target
+ * @param string $targetStr
+ * @param string $replacement
+ * @param string|false $fuzzy
+ * @param string $content
+ * @param array $otherLangContents
+ * @return self
*/
public static function newRenameJob(
- Title $target, $targetStr, $replacement, $fuzzy, $content, $otherLangContents = []
- ) {
+ Title $target,
+ string $targetStr,
+ string $replacement,
+ $fuzzy,
+ string $content,
+ array $otherLangContents = []
+ ): self {
$params = [
'target' => $targetStr,
'replacement' => $replacement,
@@ -78,6 +87,7 @@ class MessageUpdateJob extends GenericTranslateJob {
$isRename = $params['rename'] ?? false;
$isFuzzy = $params['fuzzy'] ?? false;
$otherLangs = $params['otherLangs'] ?? [];
+ $originalTitle = Title::newFromLinkTarget( $this->title->getTitleValue(), Title::NEW_CLONE );
if ( $isRename ) {
$this->title = $this->handleRename( $params['target'], $params['replacement'], $user );
@@ -90,6 +100,8 @@ class MessageUpdateJob extends GenericTranslateJob {
'target' => $params['target']
]
);
+
+ $this->removeFromCache( $originalTitle );
return true;
}
}
@@ -121,6 +133,7 @@ class MessageUpdateJob extends GenericTranslateJob {
$this->handleFuzzy( $title );
}
+ $this->removeFromCache( $originalTitle );
return true;
}
@@ -152,16 +165,10 @@ class MessageUpdateJob extends GenericTranslateJob {
$renameSummary = wfMessage( 'translate-manage-import-rename-summary' )
->inContentLanguage()->plain();
- /**
- * @var Title[] $movableTitles
- */
- foreach ( $movableTitles as $mTitle ) {
- /**
- * @var Title $sourceTitle
- * @var Title $replacementTitle
- */
- [ $sourceTitle, $replacementTitle ] = $mTitle;
- $mv = new MovePage( $sourceTitle, $replacementTitle );
+ foreach ( $movableTitles as [ $sourceTitle, $replacementTitle ] ) {
+ $mv = MediaWikiServices::getInstance()
+ ->getMovePageFactory()
+ ->newMovePage( $sourceTitle, $replacementTitle );
$status = $mv->move( $user, $renameSummary, false );
if ( !$status->isOK() ) {
@@ -278,4 +285,48 @@ class MessageUpdateJob extends GenericTranslateJob {
}
}
}
+
+ private function removeFromCache( Title $title ): void {
+ $config = MediaWikiServices::getInstance()->getMainConfig();
+
+ if ( !$config->get( 'TranslateGroupSynchronizationCache' ) ) {
+ return;
+ }
+
+ $currentTitle = $title;
+ // Check if the current title, is equal to the title passed. This condition will be
+ // true incase of rename where the old title would have been renamed.
+ if ( $this->title && $this->title->getPrefixedDBkey() !== $title->getPrefixedDBkey() ) {
+ $currentTitle = $this->title;
+ }
+
+ $sourceMessageHandle = new MessageHandle( $currentTitle );
+ $groupIds = $sourceMessageHandle->getGroupIds();
+ if ( !$groupIds ) {
+ $this->logWarning(
+ 'Could not find group Id for message title',
+ $this->getParams()
+ );
+ return;
+ }
+
+ $groupId = $groupIds[0];
+ $group = MessageGroups::getGroup( $groupId );
+
+ if ( !$group instanceof FileBasedMessageGroup ) {
+ return;
+ }
+
+ $groupSyncCache = Services::getInstance()->getGroupSynchronizationCache();
+ $messageKey = $title->getPrefixedDBkey();
+
+ if ( $groupSyncCache->isMessageBeingProcessed( $groupId, $messageKey ) ) {
+ $groupSyncCache->removeMessages( $groupId, $messageKey );
+ } else {
+ $this->logWarning(
+ "Did not find key: $messageKey; in group: $groupId in group sync cache",
+ $this->getParams()
+ );
+ }
+ }
}
diff --git a/MLEB/Translate/utils/MessageWebImporter.php b/MLEB/Translate/utils/MessageWebImporter.php
index 308eba62..2ba543c9 100644
--- a/MLEB/Translate/utils/MessageWebImporter.php
+++ b/MLEB/Translate/utils/MessageWebImporter.php
@@ -10,7 +10,7 @@
* @license GPL-2.0-or-later
*/
-use MediaWiki\Extensions\Translate\SystemUsers\FuzzyBot;
+use MediaWiki\Extension\Translate\SystemUsers\FuzzyBot;
use MediaWiki\MediaWikiServices;
use MediaWiki\Revision\SlotRecord;
@@ -19,28 +19,16 @@ use MediaWiki\Revision\SlotRecord;
* displays them in pretty way with diffs and finally executes the actions the user choices.
*/
class MessageWebImporter {
- /**
- * @var Title
- */
+ /** @var Title */
protected $title;
-
- /**
- * @var User
- */
+ /** @var User */
protected $user;
-
- /**
- * @var MessageGroup
- */
+ /** @var MessageGroup */
protected $group;
protected $code;
protected $time;
-
- /**
- * @var OutputPage
- */
+ /** @var OutputPage */
protected $out;
-
/**
* Maximum processing time in seconds.
*/
@@ -66,30 +54,22 @@ class MessageWebImporter {
return $this->title;
}
- /**
- * @param Title $title
- */
+ /** @param Title $title */
public function setTitle( Title $title ) {
$this->title = $title;
}
- /**
- * @return User
- */
+ /** @return User */
public function getUser() {
return $this->user ?: RequestContext::getMain()->getUser();
}
- /**
- * @param User $user
- */
+ /** @param User $user */
public function setUser( User $user ) {
$this->user = $user;
}
- /**
- * @return MessageGroup
- */
+ /** @return MessageGroup */
public function getGroup() {
return $this->group;
}
@@ -106,30 +86,22 @@ class MessageWebImporter {
}
}
- /**
- * @return string
- */
+ /** @return string */
public function getCode() {
return $this->code;
}
- /**
- * @param string $code
- */
+ /** @param string $code */
public function setCode( $code = 'en' ) {
$this->code = $code;
}
- /**
- * @return string
- */
+ /** @return string */
protected function getAction() {
return $this->getTitle()->getFullURL();
}
- /**
- * @return string
- */
+ /** @return string */
protected function doHeader() {
$formParams = [
'method' => 'post',
@@ -143,16 +115,12 @@ class MessageWebImporter {
Html::hidden( 'process', 1 );
}
- /**
- * @return string
- */
+ /** @return string */
protected function doFooter() {
return '</form>';
}
- /**
- * @return bool
- */
+ /** @return bool */
protected function allowProcess() {
$request = RequestContext::getMain()->getRequest();
@@ -161,9 +129,7 @@ class MessageWebImporter {
&& $this->getUser()->matchEditToken( $request->getVal( 'token' ) );
}
- /**
- * @return array
- */
+ /** @return array */
protected function getActions() {
if ( $this->code === 'en' ) {
return [ 'import', 'fuzzy', 'ignore' ];
@@ -393,7 +359,7 @@ class MessageWebImporter {
* Perform an action on a given group/key/code
*
* @param string $action Options: 'import', 'conflict' or 'ignore'
- * @param MessageGroup $group Group object
+ * @param MessageGroup $group
* @param string $key Message key
* @param string $code Language code
* @param string $message Contents for the $key/code combination
@@ -507,10 +473,7 @@ class MessageWebImporter {
);
$changed = [];
- $slots = [];
- if ( is_callable( [ $revStore, 'getContentBlobsForBatch' ] ) ) {
- $slots = $revStore->getContentBlobsForBatch( $rows, [ SlotRecord::MAIN ] )->getValue();
- }
+ $slots = $revStore->getContentBlobsForBatch( $rows, [ SlotRecord::MAIN ] )->getValue();
foreach ( $rows as $row ) {
global $wgTranslateDocumentationLanguageCode;
diff --git a/MLEB/Translate/utils/StatsBar.php b/MLEB/Translate/utils/StatsBar.php
index f663e84f..4a6aaef9 100644
--- a/MLEB/Translate/utils/StatsBar.php
+++ b/MLEB/Translate/utils/StatsBar.php
@@ -18,15 +18,9 @@ class StatsBar {
* @var int[]
*/
protected $stats;
-
- /**
- * @var string Message group id
- */
+ /** @var string Message group id */
protected $group;
-
- /**
- * @var string Language
- */
+ /** @var string Language */
protected $language;
/**
diff --git a/MLEB/Translate/utils/StatsTable.php b/MLEB/Translate/utils/StatsTable.php
index 03b9d73f..46493683 100644
--- a/MLEB/Translate/utils/StatsTable.php
+++ b/MLEB/Translate/utils/StatsTable.php
@@ -15,24 +15,13 @@
* @ingroup Stats
*/
class StatsTable {
- /**
- * @var Language
- */
+ /** @var Language */
protected $lang;
-
- /**
- * @var Title
- */
+ /** @var Title */
protected $translate;
-
- /**
- * @var string
- */
+ /** @var string */
protected $mainColumnHeader;
-
- /**
- * @var Message[]
- */
+ /** @var Message[] */
protected $extraColumns = [];
public function __construct() {
@@ -88,16 +77,12 @@ class StatsTable {
return $colors[ $index ];
}
- /**
- * @return string
- */
+ /** @return string */
public function getMainColumnHeader() {
return $this->mainColumnHeader;
}
- /**
- * @param Message $msg
- */
+ /** @param Message $msg */
public function setMainColumnHeader( Message $msg ) {
$this->mainColumnHeader = $this->createColumnHeader( $msg );
}
@@ -114,9 +99,7 @@ class StatsTable {
$this->extraColumns[] = $column;
}
- /**
- * @return Message[]
- */
+ /** @return Message[] */
public function getOtherColumnHeaders() {
return array_merge( [
wfMessage( 'translate-total' ),
@@ -127,9 +110,7 @@ class StatsTable {
], $this->extraColumns );
}
- /**
- * @return string HTML
- */
+ /** @return string HTML */
public function createHeader() {
// Create table header
$out = Html::openElement(
@@ -276,10 +257,10 @@ class StatsTable {
* @param string $code Language code
* @return bool
*/
- public function isBlacklisted( $groupId, $code ) {
+ public function isExcluded( $groupId, $code ) {
global $wgTranslateBlacklist;
- $blacklisted = null;
+ $excluded = null;
$checks = [
$groupId,
@@ -289,10 +270,10 @@ class StatsTable {
foreach ( $checks as $check ) {
if ( isset( $wgTranslateBlacklist[$check] ) && isset( $wgTranslateBlacklist[$check][$code] ) ) {
- $blacklisted = $wgTranslateBlacklist[$check][$code];
+ $excluded = $wgTranslateBlacklist[$check][$code];
}
- if ( $blacklisted !== null ) {
+ if ( $excluded !== null ) {
break;
}
}
@@ -300,32 +281,14 @@ class StatsTable {
$group = MessageGroups::getGroup( $groupId );
$languages = $group->getTranslatableLanguages();
if ( $languages !== null && !isset( $languages[$code] ) ) {
- $blacklisted = true;
+ $excluded = true;
}
$include = Hooks::run( 'Translate:MessageGroupStats:isIncluded', [ $groupId, $code ] );
if ( !$include ) {
- $blacklisted = true;
+ $excluded = true;
}
- return $blacklisted;
- }
-
- /**
- * Used to circumvent ugly tooltips when newlines are used in the
- * message content ("x\ny" becomes "x y").
- * @param string $text
- * @return string
- */
- public static function formatTooltip( $text ) {
- $wordSeparator = wfMessage( 'word-separator' )->text();
-
- $text = strtr( $text, [
- "\n" => $wordSeparator,
- "\r" => $wordSeparator,
- "\t" => $wordSeparator,
- ] );
-
- return $text;
+ return $excluded;
}
}
diff --git a/MLEB/Translate/utils/TranslateLogFormatter.php b/MLEB/Translate/utils/TranslateLogFormatter.php
index 39a1243e..24049de4 100644
--- a/MLEB/Translate/utils/TranslateLogFormatter.php
+++ b/MLEB/Translate/utils/TranslateLogFormatter.php
@@ -63,6 +63,13 @@ class TranslateLogFormatter extends LogFormatter {
return $message->isBlank() ? $value : $message->text();
}
+ /**
+ * @param Title|null $title The page
+ * @param string|null $text
+ * @param array $parameters Query parameters
+ * @return string
+ * @return-taint onlysafefor_html
+ */
protected function makePageLinkWithText(
?Title $title, $text, array $parameters = []
) {
diff --git a/MLEB/Translate/utils/TranslateMetadata.php b/MLEB/Translate/utils/TranslateMetadata.php
index c6d0027e..a0cd25f6 100644
--- a/MLEB/Translate/utils/TranslateMetadata.php
+++ b/MLEB/Translate/utils/TranslateMetadata.php
@@ -14,9 +14,7 @@ class TranslateMetadata {
/** @var array Map of (group => key => value) */
private static $cache = [];
- /**
- * @param string[] $groups List of translate groups
- */
+ /** @param string[] $groups List of translate groups */
public static function preloadGroups( array $groups ) {
$missing = array_keys( array_diff_key( array_flip( $groups ), self::$cache ) );
if ( !$missing ) {
@@ -93,12 +91,12 @@ class TranslateMetadata {
/**
* Wrapper for getting subgroups.
* @param string $groupId
- * @return string[]|bool
+ * @return string[]|null
* @since 2012-05-09
*/
- public static function getSubgroups( $groupId ) {
+ public static function getSubgroups( string $groupId ): ?array {
$groups = self::get( $groupId, 'subgroups' );
- if ( $groups !== false ) {
+ if ( is_string( $groups ) ) {
if ( strpos( $groups, '|' ) !== false ) {
$groups = explode( '|', $groups );
} else {
@@ -110,6 +108,8 @@ class TranslateMetadata {
unset( $groups[$index] );
}
}
+ } else {
+ $groups = null;
}
return $groups;
diff --git a/MLEB/Translate/utils/TranslateSandbox.php b/MLEB/Translate/utils/TranslateSandbox.php
index 0ed2ea18..125c5afb 100644
--- a/MLEB/Translate/utils/TranslateSandbox.php
+++ b/MLEB/Translate/utils/TranslateSandbox.php
@@ -10,7 +10,7 @@
use MediaWiki\Auth\AuthenticationRequest;
use MediaWiki\Auth\AuthenticationResponse;
use MediaWiki\Auth\AuthManager;
-use MediaWiki\Extensions\Translate\SystemUsers\TranslateUserManager;
+use MediaWiki\Extension\Translate\SystemUsers\TranslateUserManager;
use MediaWiki\MediaWikiServices;
use Wikimedia\ScopedCallback;
@@ -19,8 +19,6 @@ use Wikimedia\ScopedCallback;
* lot of assumptions about what happens to the user account.
*/
class TranslateSandbox {
- public static $userToCreate = null;
-
/**
* Adds a new user without doing much validation.
*
@@ -33,7 +31,7 @@ class TranslateSandbox {
public static function addUser( $name, $email, $password ) {
$user = User::newFromName( $name, 'creatable' );
- if ( !$user instanceof User ) {
+ if ( !$user ) {
throw new MWException( 'Invalid user name' );
}
@@ -83,7 +81,12 @@ class TranslateSandbox {
}
// group-translate-sandboxed group-translate-sandboxed-member
- $user->addGroup( 'translate-sandboxed' );
+ if ( method_exists( MediaWikiServices::class, 'getUserGroupManager' ) ) {
+ // MediaWiki 1.35+
+ MediaWikiServices::getInstance()->getUserGroupManager()->addUserToGroup( $user, 'translate-sandboxed' );
+ } else {
+ $user->addGroup( 'translate-sandboxed' );
+ }
return $user;
}
@@ -97,6 +100,7 @@ class TranslateSandbox {
*/
public static function deleteUser( User $user, $force = '' ) {
$uid = $user->getId();
+ $actorId = $user->getActorId();
if ( $force !== 'force' && !self::isSandboxed( $user ) ) {
throw new MWException( 'Not a sandboxed user' );
@@ -108,11 +112,10 @@ class TranslateSandbox {
$dbw->delete( 'user_groups', [ 'ug_user' => $uid ], __METHOD__ );
$dbw->delete( 'user_properties', [ 'up_user' => $uid ], __METHOD__ );
- $m = ActorMigration::newMigration();
$dbw->delete( 'actor', [ 'actor_user' => $uid ], __METHOD__ );
// Assume no joins are needed for logging or recentchanges
- $dbw->delete( 'logging', $m->getWhere( $dbw, 'log_user', $user )['conds'], __METHOD__ );
- $dbw->delete( 'recentchanges', $m->getWhere( $dbw, 'rc_user', $user )['conds'], __METHOD__ );
+ $dbw->delete( 'logging', [ 'log_actor' => $actorId ], __METHOD__ );
+ $dbw->delete( 'recentchanges', [ 'rc_actor' => $actorId ], __METHOD__ );
// Update the site stats
$statsUpdate = SiteStatsUpdate::factory( [ 'users' => -1 ] );
@@ -170,13 +173,33 @@ class TranslateSandbox {
throw new MWException( 'Not a sandboxed user' );
}
- $user->removeGroup( 'translate-sandboxed' );
- if ( $wgTranslateSandboxPromotedGroup ) {
- $user->addGroup( $wgTranslateSandboxPromotedGroup );
+ $services = MediaWikiServices::getInstance();
+
+ if ( method_exists( $services, 'getUserGroupManager' ) ) {
+ // MediaWiki 1.35+
+ $userGroupManager = $services->getUserGroupManager();
+ $userGroupManager->removeUserFromGroup( $user, 'translate-sandboxed' );
+
+ if ( $wgTranslateSandboxPromotedGroup ) {
+ $userGroupManager->addUserToGroup( $user, $wgTranslateSandboxPromotedGroup );
+ }
+ } else {
+ $user->removeGroup( 'translate-sandboxed' );
+
+ if ( $wgTranslateSandboxPromotedGroup ) {
+ $user->addGroup( $wgTranslateSandboxPromotedGroup );
+ }
}
- $user->setOption( 'translate-sandbox-reminders', '' );
- $user->saveSettings();
+ if ( method_exists( $services, 'getUserOptionsManager' ) ) {
+ // MW 1.35+
+ $userOptionsManager = $services->getUserOptionsManager();
+ $userOptionsManager->setOption( $user, 'translate-sandbox-reminders', '' );
+ $userOptionsManager->saveOptions( $user );
+ } else {
+ $user->setOption( 'translate-sandbox-reminders', '' );
+ $user->saveSettings();
+ }
}
/**
@@ -247,11 +270,15 @@ class TranslateSandbox {
* @since 2013.06
*/
public static function isSandboxed( User $user ) {
- if ( in_array( 'translate-sandboxed', $user->getGroups(), true ) ) {
- return true;
+ if ( method_exists( MediaWikiServices::class, 'getUserGroupManager' ) ) {
+ // MediaWiki 1.35+
+ $userGroupManager = MediaWikiServices::getInstance()->getUserGroupManager();
+ $groups = $userGroupManager->getUserGroups( $user );
+ } else {
+ $groups = $user->getGroups();
}
- return false;
+ return in_array( 'translate-sandboxed', $groups, true );
}
/**
@@ -295,7 +322,7 @@ class TranslateSandbox {
}
/**
- * Whitelisting for certain API modules. See also enforcePermissions.
+ * Inclusion listing for certain API modules. See also enforcePermissions.
* Hook: ApiCheckCanExecute
* @param ApiBase $module
* @param User $user
@@ -303,7 +330,7 @@ class TranslateSandbox {
* @return bool
*/
public static function onApiCheckCanExecute( ApiBase $module, User $user, &$message ) {
- $whitelist = [
+ $inclusionList = [
// Obviously this is needed to get out of the sandbox
'ApiTranslationStash',
// Used by UniversalLanguageSelector for example
@@ -312,7 +339,7 @@ class TranslateSandbox {
if ( self::isSandboxed( $user ) ) {
$class = get_class( $module );
- if ( $module->isWriteMode() && !in_array( $class, $whitelist, true ) ) {
+ if ( $module->isWriteMode() && !in_array( $class, $inclusionList, true ) ) {
$message = ApiMessage::create( 'apierror-writeapidenied' );
return false;
}
diff --git a/MLEB/Translate/utils/TranslateSandboxEmailJob.php b/MLEB/Translate/utils/TranslateSandboxEmailJob.php
index 4c3716b9..1c078e6f 100644
--- a/MLEB/Translate/utils/TranslateSandboxEmailJob.php
+++ b/MLEB/Translate/utils/TranslateSandboxEmailJob.php
@@ -51,11 +51,16 @@ class TranslateSandboxEmailJob extends Job {
$reminders = $user->getOption( 'translate-sandbox-reminders' );
$reminders = $reminders ? explode( '|', $reminders ) : [];
$reminders[] = wfTimestamp();
- $user->setOption( 'translate-sandbox-reminders', implode( '|', $reminders ) );
- $reminders = $user->getOption( 'translate-sandbox-reminders' );
- $user->setOption( 'translate-sandbox-reminders', $reminders );
- $user->saveSettings();
+ if ( method_exists( $services, 'getUserOptionsManager' ) ) {
+ // MW 1.35+
+ $userOptionsManager = $services->getUserOptionsManager();
+ $userOptionsManager->setOption( $user, 'translate-sandbox-reminders', implode( '|', $reminders ) );
+ $userOptionsManager->saveOptions( $user );
+ } else {
+ $user->setOption( 'translate-sandbox-reminders', implode( '|', $reminders ) );
+ $user->saveSettings();
+ }
}
return $isOK;
diff --git a/MLEB/Translate/utils/TranslateToolbox.php b/MLEB/Translate/utils/TranslateToolbox.php
index 0836f485..9503f3ab 100644
--- a/MLEB/Translate/utils/TranslateToolbox.php
+++ b/MLEB/Translate/utils/TranslateToolbox.php
@@ -48,7 +48,7 @@ class TranslateToolbox {
/**
* This handler will be called for MW >= 1.35
*
- * @param Skin $skin The skin
+ * @param Skin $skin
* @param array &$sidebar Array with sidebar items
*
* @return void
diff --git a/MLEB/Translate/utils/TranslationHelpers.php b/MLEB/Translate/utils/TranslationHelpers.php
index 9b585c72..38ee5acb 100644
--- a/MLEB/Translate/utils/TranslationHelpers.php
+++ b/MLEB/Translate/utils/TranslationHelpers.php
@@ -19,24 +19,18 @@ class TranslationHelpers {
* @since 2012-01-04
*/
protected $handle;
-
- /**
- * @var TranslationAidDataProvider
- */
+ /** @var TranslationAidDataProvider */
private $dataProvider;
-
/**
* The group object of the message (or null if there isn't any)
* @var MessageGroup|null
*/
protected $group;
-
/**
* The current translation.
* @var string
*/
private $translation;
-
/**
* HTML id to the text area that contains the translation. Used to insert
* suggestion directly into the text area, for example.
@@ -79,21 +73,13 @@ class TranslationHelpers {
/**
* Gets the HTML id of the text area that contains the translation.
- * @return String
+ * @return string
*/
public function getTextareaId() {
return $this->textareaId;
}
/**
- * Sets the HTML id of the text area that contains the translation.
- * @param string $id
- */
- public function setTextareaId( $id ) {
- $this->textareaId = $id;
- }
-
- /**
* Enable or disable extra help for editing.
* @param bool $mode
*/
@@ -152,29 +138,10 @@ class TranslationHelpers {
}
/**
- * Gets the linguistically correct language code for translation
- * @return string
- */
- public function getTargetLanguage() {
- global $wgLanguageCode, $wgTranslateDocumentationLanguageCode;
-
- $code = $this->handle->getCode();
- if ( !$code ) {
- $this->mustBeKnownMessage();
- $code = $this->group->getSourceLanguage();
- }
- if ( $code === $wgTranslateDocumentationLanguageCode ) {
- return $wgLanguageCode;
- }
-
- return $code;
- }
-
- /**
* Returns block element HTML snippet that contains the translation aids.
* Not all boxes are shown all the time depending on whether they have
* any information to show and on configuration variables.
- * @return String Block level HTML snippet or empty string.
+ * @return string Block level HTML snippet or empty string.
*/
public function getBoxes() {
// Box filter
@@ -218,13 +185,8 @@ class TranslationHelpers {
}
}
- /**
- * @return array
- */
- public function getBoxNames() {
+ public function getBoxNames(): array {
return [
- 'other-languages' => [ $this, 'getOtherLanguagesBox' ],
- 'separator' => [ $this, 'getSeparatorBox' ],
'documentation' => [ $this, 'getDocumentationBox' ],
'definition' => [ $this, 'getDefinitionBox' ],
];
@@ -234,20 +196,11 @@ class TranslationHelpers {
$this->mustHaveDefinition();
$en = $this->getDefinition();
- $title = Linker::link(
- SpecialPage::getTitleFor( 'Translate' ),
- htmlspecialchars( $this->group->getLabel() ),
- [],
- [
- 'group' => $this->group->getId(),
- 'language' => $this->handle->getCode()
- ]
- );
-
+ $linkTag = self::ajaxEditLink( $this->handle->getTitle(), $this->group->getLabel() );
$label =
wfMessage( 'translate-edit-definition' )->escaped() .
wfMessage( 'word-separator' )->escaped() .
- wfMessage( 'parentheses' )->rawParams( $title )->escaped();
+ wfMessage( 'parentheses' )->rawParams( $linkTag )->escaped();
// Source language object
$sl = Language::factory( $this->group->getSourceLanguage() );
@@ -265,89 +218,11 @@ class TranslationHelpers {
$msg .= $this->wrapInsert( $id, $en );
- $class = [ 'class' => 'mw-sp-translate-edit-definition mw-translate-edit-definition' ];
-
- return TranslateUtils::fieldset( $label, $msg, $class );
- }
-
- public function getTranslationDisplayBox() {
- $en = $this->getTranslation();
- if ( $en === null ) {
- return null;
- }
- $label = wfMessage( 'translate-edit-translation' )->escaped();
- $class = [ 'class' => 'mw-translate-edit-translation' ];
- $msg = Html::rawElement( 'span',
- [ 'class' => 'mw-translate-edit-translationtext' ],
- TranslateUtils::convertWhiteSpaceToHTML( $en )
- );
+ $class = [ 'class' => 'mw-sp-translate-edit-definition' ];
return TranslateUtils::fieldset( $label, $msg, $class );
}
- public function getOtherLanguagesBox() {
- $code = $this->handle->getCode();
- $page = $this->handle->getKey();
- $ns = $this->handle->getTitle()->getNamespace();
-
- $boxes = [];
- foreach ( self::getFallbacks( $code ) as $fbcode ) {
- $text = TranslateUtils::getMessageContent( $page, $fbcode, $ns );
- if ( $text === null ) {
- continue;
- }
-
- $fbLanguage = Language::factory( $fbcode );
- $context = RequestContext::getMain();
- $label = TranslateUtils::getLanguageName( $fbcode, $context->getLanguage()->getCode() ) .
- $context->msg( 'word-separator' )->text() .
- $context->msg( 'parentheses', $fbLanguage->getHtmlCode() )->text();
-
- $target = $this->handle->getTitleForLanguage( $fbcode );
-
- if ( $target ) {
- $label = self::ajaxEditLink( $target, $label );
- }
-
- $dialogID = $this->dialogID();
- $id = Sanitizer::escapeIdForAttribute( "other-$fbcode-$dialogID" );
-
- $params = [ 'class' => 'mw-translate-edit-item' ];
-
- $display = TranslateUtils::convertWhiteSpaceToHTML( $text );
- $display = Html::rawElement( 'div', [
- 'lang' => $fbLanguage->getHtmlCode(),
- 'dir' => $fbLanguage->getDir() ],
- $display
- );
-
- $contents = self::legend( $label ) . "\n" . $this->adder( $id, $fbLanguage ) .
- $display . self::clear();
-
- $boxes[] = Html::rawElement( 'div', $params, $contents ) .
- $this->wrapInsert( $id, $text );
- }
-
- if ( count( $boxes ) ) {
- $sep = Html::element( 'hr', [ 'class' => 'mw-translate-sep' ] );
-
- return TranslateUtils::fieldset(
- wfMessage(
- 'translate-edit-in-other-languages',
- $page
- )->escaped(),
- implode( "$sep\n", $boxes ),
- [ 'class' => 'mw-sp-translate-edit-inother' ]
- );
- }
-
- return null;
- }
-
- public function getSeparatorBox() {
- return Html::element( 'div', [ 'class' => 'mw-translate-edit-extra' ] );
- }
-
public function getDocumentationBox() {
global $wgTranslateDocumentationLanguageCode;
@@ -388,60 +263,7 @@ class TranslationHelpers {
);
}
- /**
- * @param string $label
- * @return string
- */
- protected static function legend( $label ) {
- # Float it to the opposite direction
- return Html::rawElement( 'div', [ 'class' => 'mw-translate-legend' ], $label );
- }
-
- /**
- * @return string
- */
- protected static function clear() {
- return Html::element( 'div', [ 'style' => 'clear:both;' ] );
- }
-
- /**
- * @param string $code
- * @return array
- */
- protected static function getFallbacks( $code ) {
- global $wgTranslateLanguageFallbacks;
-
- // User preference has the final say
- $user = RequestContext::getMain()->getUser();
- $preference = $user->getOption( 'translate-editlangs' );
- if ( $preference !== 'default' ) {
- $fallbacks = array_map( 'trim', explode( ',', $preference ) );
- foreach ( $fallbacks as $k => $v ) {
- if ( $v === $code ) {
- unset( $fallbacks[$k] );
- }
- }
-
- return $fallbacks;
- }
-
- // Global configuration settings
- $fallbacks = [];
- if ( isset( $wgTranslateLanguageFallbacks[$code] ) ) {
- $fallbacks = (array)$wgTranslateLanguageFallbacks[$code];
- }
-
- $list = Language::getFallbacksFor( $code );
- array_pop( $list ); // Get 'en' away from the end
- $fallbacks = array_merge( $list, $fallbacks );
-
- return array_unique( $fallbacks );
- }
-
- /**
- * @return string
- */
- public function dialogID() {
+ public function dialogID(): string {
$hash = sha1( $this->handle->getTitle()->getPrefixedDBkey() );
return substr( $hash, 0, 4 );
@@ -449,7 +271,7 @@ class TranslationHelpers {
/**
* @param string $source jQuery selector for element containing the source
- * @param Language $lang Language object
+ * @param Language $lang
* @return string
*/
public function adder( $source, $lang ) {