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 $group = $data[
'EXTRA'][
'METADATA'][
'group'];
99 $code = $data[
'EXTRA'][
'METADATA'][
'code'];
101 if ( !MessageGroups::exists( $group ) ) {
102 $errorWrap =
"<div class='error'>\n$1\n</div>";
103 $this->getOutput()->wrapWikiMsg( $errorWrap,
'translate-import-err-stale-group' );
109 $importer->setUser( $this->getUser() );
110 $alldone = $importer->execute( $messages );
113 $this->deleteCachedData();
122 private function checkError( array $msg ): bool {
127 if ( $msg[0] !==
'ok' ) {
128 $errorWrap =
"<div class='error'>\n$1\n</div>";
129 $msg[0] =
'translate-import-err-' . $msg[0];
130 $this->getOutput()->wrapWikiMsg( $errorWrap, $msg );
140 private function outputForm(): void {
141 $this->getOutput()->addModules(
'ext.translate.special.importtranslations' );
142 $this->getOutput()->addHelpLink(
'Help:Extension:Translate/Off-line_translation' );
144 $this->getOutput()->addHTML(
145 Xml::openElement(
'form', [
146 'action' => $this->getPageTitle()->getLocalURL(),
148 'enctype' =>
'multipart/form-data',
149 'id' =>
'mw-translate-import',
151 Html::hidden(
'token', $this->getContext()->getCsrfTokenSet()->getToken() ) .
152 Html::hidden(
'title', $this->getPageTitle()->getPrefixedText() ) .
154 $this->msg(
'translate-import-from-local' )->text(),
156 'mw-translate-up-local-input',
158 $this->getRequest()->getText(
'upload-local' ),
161 Xml::submitButton( $this->msg(
'translate-import-load' )->text() ) .
162 Xml::closeElement(
'form' )
167 private function loadFile( ?
string &$filedata ): array {
168 $filename = $this->getRequest()->getFileTempname(
'upload-local' );
170 if ( !is_uploaded_file( $filename ) ) {
171 return [
'ul-failed' ];
174 $filedata = file_get_contents( $filename );
180 private function parseFile(
string $data ): array {
195 '@phan-var FileBasedMessageGroup $group';
200 $parseOutput = $ffs->readFromVariable( $data );
202 return [
'no-headers' ];
206 $metadata = $parseOutput[
'EXTRA'][
'METADATA'];
209 if ( !isset( $metadata[
'code'] ) || !isset( $metadata[
'group'] ) ) {
210 return [
'no-headers' ];
213 return [
'ok', $parseOutput ];
216 private function setCachedData( $data ): void {
217 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
218 $this->cache->set( $key, $data, 60 * 30 );
221 private function getCachedData() {
222 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
224 return $this->cache->get( $key );
227 private function deleteCachedData(): bool {
228 $key = $this->cache->makeKey(
'translate',
'webimport', $this->getUser()->getId() );
230 return $this->cache->delete( $key );
New-style FFS class that implements support for gettext file format.
Exception thrown when a Gettext file could not be parsed, such as when missing required headers.