Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 78 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
ImportTranslationsFromCsv | |
0.00% |
0 / 78 |
|
0.00% |
0 / 4 |
210 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 26 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
90 | |||
progressReporter | |
0.00% |
0 / 12 |
|
0.00% |
0 / 1 |
12 | |||
filterEmptyTranslations | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\MessageGroupProcessing; |
5 | |
6 | use MediaWiki\Extension\Translate\Services; |
7 | use MediaWiki\Extension\Translate\Utilities\BaseMaintenanceScript; |
8 | use MediaWiki\MediaWikiServices; |
9 | use MediaWiki\Title\Title; |
10 | |
11 | /** |
12 | * Script to import translations from a CSV file |
13 | * @since 2022.06 |
14 | * @license GPL-2.0-or-later |
15 | * @author Abijeet Patro |
16 | */ |
17 | class ImportTranslationsFromCsv extends BaseMaintenanceScript { |
18 | public function __construct() { |
19 | parent::__construct(); |
20 | $this->addDescription( 'Import translations for a CSV file' ); |
21 | |
22 | $this->addArg( |
23 | 'file', |
24 | 'Path to CSV file to import', |
25 | self::REQUIRED |
26 | ); |
27 | |
28 | $this->addOption( |
29 | 'summary', |
30 | 'The change summary when updating the translations', |
31 | self::REQUIRED, |
32 | self::HAS_ARG |
33 | ); |
34 | |
35 | $this->addOption( |
36 | 'user', |
37 | 'User ID of the user performing the import', |
38 | self::REQUIRED, |
39 | self::HAS_ARG |
40 | ); |
41 | |
42 | $this->addOption( |
43 | 'really', |
44 | 'Should the import actually be performed', |
45 | self::OPTIONAL, |
46 | self::NO_ARG |
47 | ); |
48 | |
49 | $this->requireExtension( 'Translate' ); |
50 | } |
51 | |
52 | public function execute() { |
53 | $csvFilePath = $this->getArg( 0 ); |
54 | |
55 | $username = $this->getOption( 'user' ); |
56 | $summary = $this->getOption( 'summary' ); |
57 | |
58 | // Validate the parameters |
59 | if ( trim( $summary ) === '' ) { |
60 | $this->fatalError( 'Please provide a non-empty "summary"' ); |
61 | } |
62 | |
63 | $userFactory = MediaWikiServices::getInstance()->getUserFactory(); |
64 | $user = $userFactory->newFromName( $username ); |
65 | |
66 | if ( $user === null || !$user->isRegistered() ) { |
67 | $this->fatalError( "User $username does not exist." ); |
68 | } |
69 | |
70 | // Validate and parse the CSV file |
71 | $csvImporter = Services::getInstance()->getCsvTranslationImporter(); |
72 | $status = $csvImporter->parseFile( $csvFilePath ); |
73 | |
74 | if ( $status->isOK() ) { |
75 | $messagesWithTranslations = $status->getValue(); |
76 | $output = "\n"; |
77 | foreach ( $messagesWithTranslations as $messageTranslations ) { |
78 | $translations = $messageTranslations[ 'translations' ]; |
79 | $output .= '* ' . count( $this->filterEmptyTranslations( $translations ) ) . |
80 | ' translation(s) to import for ' . |
81 | $messageTranslations['messageTitle'] . "\n"; |
82 | } |
83 | |
84 | $this->output( $output . "\n" ); |
85 | } else { |
86 | $this->error( "Error during processing:\n" ); |
87 | $this->error( (string)$status ); |
88 | $this->fatalError( 'Exiting...' ); |
89 | } |
90 | |
91 | if ( !$this->hasOption( 'really' ) ) { |
92 | $this->output( "\nUse option --really to perform the import.\n" ); |
93 | return true; |
94 | } |
95 | |
96 | // Start the actual import of translations |
97 | $this->output( "\nProceeding with import...\n\n" ); |
98 | $importStatus = $csvImporter->importData( |
99 | $status->getValue(), $user, trim( $summary ), [ $this, 'progressReporter' ] |
100 | ); |
101 | |
102 | if ( $importStatus->isOK() ) { |
103 | $this->output( "\nSuccess: Import done\n" ); |
104 | } else { |
105 | $this->output( "\nImport failed. See errors:\n" ); |
106 | $failedImportStatuses = $importStatus->getValue(); |
107 | foreach ( $failedImportStatuses as $translationTitleText => $status ) { |
108 | $this->output( "\nImport failed for $translationTitleText:\n" ); |
109 | $this->output( $status ); |
110 | } |
111 | |
112 | return false; |
113 | } |
114 | |
115 | return true; |
116 | } |
117 | |
118 | public function progressReporter( |
119 | Title $title, |
120 | array $messageImportStatuses, |
121 | int $total, |
122 | int $processed |
123 | ): void { |
124 | $paddedProcessed = str_pad( (string)$processed, strlen( (string)$total ), ' ', STR_PAD_LEFT ); |
125 | $progressCounter = "($paddedProcessed/$total)"; |
126 | |
127 | $successCount = 0; |
128 | $failCount = 0; |
129 | foreach ( $messageImportStatuses as $messageImportStatus ) { |
130 | if ( $messageImportStatus->isOK() ) { |
131 | $successCount++; |
132 | } else { |
133 | $failCount++; |
134 | } |
135 | } |
136 | |
137 | $this->output( |
138 | "$progressCounter Imported translations for {$title->getPrefixedText()} with $failCount " . |
139 | "failure(s) and $successCount successful import(s) ...\n" |
140 | ); |
141 | } |
142 | |
143 | private function filterEmptyTranslations( array $translations ): array { |
144 | return array_filter( $translations, 'strlen' ); |
145 | } |
146 | } |