26 private BagOStuff $cache;
28 public function __construct( BagOStuff $cache ) {
29 parent::__construct(
'ImportTranslations',
'translate-import' );
30 $this->cache = $cache;
33 public function doesWrites() {
37 protected function getGroupName() {
50 if ( !$this->userCanExecute( $this->getUser() ) ) {
51 $this->displayRestrictionError();
54 if ( !$this->getRequest()->wasPosted() ) {
60 $csrfTokenSet = $this->getContext()->getCsrfTokenSet();
61 if ( !$csrfTokenSet->matchTokenField(
'token' ) ) {
62 $this->getOutput()->addWikiMsg(
'session_fail_preview' );
68 if ( $this->getRequest()->getCheck(
'process' ) ) {
69 $data = $this->getCachedData();
71 $this->getOutput()->addWikiMsg(
'session_fail_preview' );
82 $msg = $this->loadFile( $file );
83 if ( $this->checkError( $msg ) ) {
87 $msg = $this->parseFile( $file );
88 if ( $this->checkError( $msg ) ) {
93 $this->setCachedData( $data );
96 $messages = $data[
'MESSAGES'];
97 $groupId = $data[
'EXTRA'][
'METADATA'][
'group'];
98 $code = $data[
'EXTRA'][
'METADATA'][
'code'];
100 if ( !MessageGroups::exists( $groupId ) ) {
101 $errorWrap =
"<div class='error'>\n$1\n</div>";
102 $this->getOutput()->wrapWikiMsg( $errorWrap,
'translate-import-err-stale-group' );
107 $importer =
new MessageWebImporter( $this->getPageTitle(), $this->getUser(), $groupId, $code );
108 $allDone = $importer->execute( $messages );
110 $out = $this->getOutput();
111 $pageTitle = $this->getPageTitle();
114 $this->deleteCachedData();
118 $out->addBacklinkSubtitle( $pageTitle );
126 private function checkError( array $msg ): bool {
131 if ( $msg[0] !==
'ok' ) {
132 $errorWrap =
"<div class='error'>\n$1\n</div>";
133 $msg[0] =
'translate-import-err-' . $msg[0];
134 $this->getOutput()->wrapWikiMsg( $errorWrap, $msg );
144 private function outputForm(): void {
145 $this->getOutput()->addModules(
'ext.translate.special.importtranslations' );
146 $this->getOutput()->addHelpLink(
'Help:Extension:Translate/Off-line_translation' );
148 $this->getOutput()->addHTML(
149 Xml::openElement(
'form', [
150 'action' => $this->getPageTitle()->getLocalURL(),
152 'enctype' =>
'multipart/form-data',
153 'id' =>
'mw-translate-import',
155 Html::hidden(
'token', $this->getContext()->getCsrfTokenSet()->getToken() ) .
156 Html::hidden(
'title', $this->getPageTitle()->getPrefixedText() ) .
158 $this->msg(
'translate-import-from-local' )->text(),
160 'mw-translate-up-local-input',
162 $this->getRequest()->getText(
'upload-local' ),
165 Xml::submitButton( $this->msg(
'translate-import-load' )->text() ) .
166 Xml::closeElement(
'form' )
171 private function loadFile( ?
string &$filedata ): array {
172 $filename = $this->getRequest()->getFileTempname(
'upload-local' );
174 if ( !is_uploaded_file( $filename ) ) {
175 return [
'ul-failed' ];
178 $filedata = file_get_contents( $filename );
184 private function parseFile(
string $data ): array {
191 'format' =>
'Gettext',
199 '@phan-var FileBasedMessageGroup $group';
201 $ffs =
new GettextFormat( $group );
204 $parseOutput = $ffs->readFromVariable( $data );
205 }
catch ( GettextParseException $e ) {
206 return [
'no-headers' ];
210 $metadata = $parseOutput[
'EXTRA'][
'METADATA'];
213 if ( !isset( $metadata[
'code'] ) || !isset( $metadata[
'group'] ) ) {
214 return [
'no-headers' ];
217 return [
'ok', $parseOutput ];
220 private function setCachedData( $data ): void {
221 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
222 $this->cache->set( $key, $data, 60 * 30 );
225 private function getCachedData() {
226 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
228 return $this->cache->get( $key );
231 private function deleteCachedData(): bool {
232 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
234 return $this->cache->delete( $key );