29 public function __construct( BagOStuff $cache ) {
30 parent::__construct(
'ImportTranslations',
'translate-import' );
31 $this->cache = $cache;
34 public function doesWrites() {
38 protected function getGroupName() {
51 if ( !$this->userCanExecute( $this->getUser() ) ) {
52 $this->displayRestrictionError();
55 if ( !$this->getRequest()->wasPosted() ) {
61 $csrfTokenSet = $this->getContext()->getCsrfTokenSet();
62 if ( !$csrfTokenSet->matchTokenField(
'token' ) ) {
63 $this->getOutput()->addWikiMsg(
'session_fail_preview' );
69 if ( $this->getRequest()->getCheck(
'process' ) ) {
70 $data = $this->getCachedData();
72 $this->getOutput()->addWikiMsg(
'session_fail_preview' );
83 $msg = $this->loadFile( $file );
84 if ( $this->checkError( $msg ) ) {
88 $msg = $this->parseFile( $file );
89 if ( $this->checkError( $msg ) ) {
94 $this->setCachedData( $data );
97 $messages = $data[
'MESSAGES'];
98 $groupId = $data[
'EXTRA'][
'METADATA'][
'group'];
99 $code = $data[
'EXTRA'][
'METADATA'][
'code'];
101 if ( !MessageGroups::exists( $groupId ) ) {
102 $errorWrap =
"<div class='error'>\n$1\n</div>";
103 $this->getOutput()->wrapWikiMsg( $errorWrap,
'translate-import-err-stale-group' );
108 $importer =
new MessageWebImporter( $this->getPageTitle(), $this->getUser(), $groupId, $code );
109 $allDone = $importer->execute( $messages );
111 $out = $this->getOutput();
112 $pageTitle = $this->getPageTitle();
115 $this->deleteCachedData();
119 $out->addBacklinkSubtitle( $pageTitle );
127 private function checkError( array $msg ): bool {
132 if ( $msg[0] !==
'ok' ) {
133 $errorWrap =
"<div class='error'>\n$1\n</div>";
134 $msg[0] =
'translate-import-err-' . $msg[0];
135 $this->getOutput()->wrapWikiMsg( $errorWrap, $msg );
145 private function outputForm(): void {
146 $this->getOutput()->addModules(
'ext.translate.special.importtranslations' );
147 $this->getOutput()->addHelpLink(
'Help:Extension:Translate/Off-line_translation' );
149 $this->getOutput()->addHTML(
150 Xml::openElement(
'form', [
151 'action' => $this->getPageTitle()->getLocalURL(),
153 'enctype' =>
'multipart/form-data',
154 'id' =>
'mw-translate-import',
156 Html::hidden(
'token', $this->getContext()->getCsrfTokenSet()->getToken() ) .
157 Html::hidden(
'title', $this->getPageTitle()->getPrefixedText() ) .
159 $this->msg(
'translate-import-from-local' )->text(),
161 'mw-translate-up-local-input',
163 $this->getRequest()->getText(
'upload-local' ),
166 Xml::submitButton( $this->msg(
'translate-import-load' )->text() ) .
167 Xml::closeElement(
'form' )
172 private function loadFile( ?
string &$filedata ): array {
173 $filename = $this->getRequest()->getFileTempname(
'upload-local' );
175 if ( !is_uploaded_file( $filename ) ) {
176 return [
'ul-failed' ];
179 $filedata = file_get_contents( $filename );
185 private function parseFile(
string $data ): array {
192 'format' =>
'Gettext',
200 '@phan-var FileBasedMessageGroup $group';
202 $ffs =
new GettextFormat( $group );
205 $parseOutput = $ffs->readFromVariable( $data );
206 }
catch ( GettextParseException $e ) {
207 return [
'no-headers' ];
211 $metadata = $parseOutput[
'EXTRA'][
'METADATA'];
214 if ( !isset( $metadata[
'code'] ) || !isset( $metadata[
'group'] ) ) {
215 return [
'no-headers' ];
218 return [
'ok', $parseOutput ];
221 private function setCachedData( $data ): void {
222 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
223 $this->cache->set( $key, $data, 60 * 30 );
226 private function getCachedData() {
227 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
229 return $this->cache->get( $key );
232 private function deleteCachedData(): bool {
233 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
235 return $this->cache->delete( $key );