36 public function __construct() {
37 parent::__construct();
38 $this->addDescription(
'Script for processing message changes in file based message groups' );
41 '(optional) Comma separated list of group IDs to process (can use * as wildcard). ' .
48 '(optional) Comma separated list of group IDs to not process (can use * ' .
49 'as wildcard). Overrides --group parameter.',
55 '(optional) Unique name to avoid conflicts with multiple invocations of this script.',
61 '(optional) Import "safe" changes: message additions when no other kind of changes.'
64 'skip-group-sync-check',
65 '(optional) Skip importing group if synchronization is still in progress or if there ' .
66 'was an error during synchronization. See: ' .
67 'https://www.mediawiki.org/wiki/Help:Extension:Translate/Group_management#Strong_synchronization'
69 $this->requireExtension(
'Translate' );
72 public function execute() {
73 $name = $this->getOption(
'name', MessageChangeStorage::DEFAULT_NAME );
74 if ( !MessageChangeStorage::isValidCdbName( $name ) ) {
75 $this->fatalError(
'Invalid name' );
82 $scripted = $this->hasOption(
'safe-import' );
83 $skipGroupSyncCache = $this->hasOption(
'skip-group-sync-check' );
85 $services = Services::getInstance();
86 $groupSyncCache = $services->getGroupSynchronizationCache();
87 $groupSyncCacheEnabled = MediaWikiServices::getInstance()->getMainConfig()
88 ->get(
'TranslateGroupSynchronizationCache' );
91 foreach ( $groups as $id => $group ) {
92 if ( $groupSyncCacheEnabled && !$skipGroupSyncCache ) {
93 if ( $groupSyncCache->isGroupBeingProcessed( $id ) ) {
94 $this->error(
"Group $id is currently being synchronized; skipping processing of changes\n" );
98 if ( $groupSyncCache->groupHasErrors( $id ) ) {
99 $this->error(
"Skipping $id due to an error during synchronization\n" );
105 $this->output(
"Processing $id\n" );
108 $changes[$id] = $comparator->processGroup( $group, $comparator::ALL_LANGUAGES );
109 }
catch ( Exception $e ) {
110 $errorMsg =
"Exception occurred while processing group: $id.\nException: $e";
111 $this->error( $errorMsg );
112 error_log( $errorMsg );
121 if ( $changes === [] ) {
123 $this->output(
"No changes found\n" );
130 $importer = $services->getExternalMessageSourceStateImporter();
131 $info = $importer->importSafe( $changes, $name );
132 $this->printChangeInfo( $info );
137 $file = MessageChangeStorage::getCdbPath( $name );
139 MessageChangeStorage::writeChanges( $changes, $file );
140 $url = SpecialPage::getTitleFor(
'ManageMessageGroups', $name )->getFullURL();
141 $this->output(
"Process changes at $url\n" );
149 $groups = MessageGroups::getGroupsByType( FileBasedMessageGroup::class );
152 $include = $this->getOption(
'group',
'*' );
153 $include = explode(
',', $include );
154 $include = array_map(
'trim', $include );
155 $include = MessageGroups::expandWildcards( $include );
158 $exclude = $this->getOption(
'skipgroup',
'' );
159 $exclude = explode(
',', $exclude );
160 $exclude = array_map(
'trim', $exclude );
161 $exclude = MessageGroups::expandWildcards( $exclude );
164 $include = array_flip( $include );
165 $exclude = array_flip( $exclude );
167 $groups = array_filter( $groups,
168 static function (
MessageGroup $group ) use ( $include, $exclude ) {
169 $id = $group->
getId();
171 return isset( $include[$id] ) && !isset( $exclude[$id] );
178 protected function printChangeInfo( array $info ) {
179 foreach ( $info[
'processed'] as $group => $languages ) {
180 $newMessageCount = array_sum( $languages );
181 if ( $newMessageCount ) {
182 $this->output(
"Imported $newMessageCount new messages or translations for $group.\n" );
186 if ( $info[
'skipped'] !== [] ) {
187 $skipped = implode(
', ', array_keys( $info[
'skipped'] ) );
188 $this->output(
"There are changes to check for groups $skipped.\n" );
189 $url = SpecialPage::getTitleFor(
'ManageMessageGroups', $info[
'name'] )->getFullURL();
190 $this->output(
"You can process them at $url\n" );