Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
PremadeMediawikiExtensionGroups.php
Go to the documentation of this file.
1<?php
12
18 protected $idPrefix = 'ext-';
20 protected $namespace;
25 protected $path;
30 protected $definitionFile;
31
40 public function __construct( $def, $path ) {
41 $this->definitionFile = $def;
42 $this->path = rtrim( $path, '/' );
43 }
44
50 protected function getDefaultNamespace() {
51 return NS_MEDIAWIKI;
52 }
53
59 protected function getNamespace() {
60 if ( $this->namespace === null ) {
61 $this->namespace = $this->getDefaultNamespace();
62 }
63 return $this->namespace;
64 }
65
72 public function setGroupPrefix( $value ) {
73 $this->idPrefix = $value;
74 }
75
82 public function setNamespace( $value ) {
83 $this->namespace = $value;
84 }
85
92 public function register( array &$list, array &$deps ) {
93 $groups = $this->parseFile();
94 $groups = $this->processGroups( $groups );
95 foreach ( $groups as $id => $g ) {
96 $list[$id] = $this->createMessageGroup( $id, $g );
97 }
98
99 $deps[] = new FileDependency( $this->definitionFile );
100
101 return true;
102 }
103
110 protected function createMessageGroup( $id, $info ) {
111 $conf = [];
112 $conf['BASIC']['class'] = MediaWikiExtensionMessageGroup::class;
113 $conf['BASIC']['id'] = $id;
114 $conf['BASIC']['namespace'] = $this->getNamespace();
115 $conf['BASIC']['label'] = $info['name'];
116
117 if ( isset( $info['desc'] ) ) {
118 $conf['BASIC']['description'] = $info['desc'];
119 } else {
120 $conf['BASIC']['descriptionmsg'] = $info['descmsg'];
121 }
122
123 $conf['FILES']['class'] = JsonFFS::class;
124 $conf['FILES']['sourcePattern'] = $this->path . '/' . $info['file'];
125
126 // @todo Find a better way
127 if ( isset( $info['aliasfile'] ) ) {
128 $conf['FILES']['aliasFileSource'] = $this->path . '/' . $info['aliasfile'];
129 $conf['FILES']['aliasFile'] = $info['aliasfile'];
130 }
131 if ( isset( $info['magicfile'] ) ) {
132 $conf['FILES']['magicFileSource'] = $this->path . '/' . $info['magicfile'];
133 $conf['FILES']['magicFile'] = $info['magicfile'];
134 }
135
136 if ( isset( $info['prefix'] ) ) {
137 $conf['MANGLER']['class'] = StringMatcher::class;
138 $conf['MANGLER']['prefix'] = $info['prefix'];
139 $conf['MANGLER']['patterns'] = $info['mangle'];
140
141 $mangler = new StringMatcher( $info['prefix'], $info['mangle'] );
142 if ( isset( $info['ignored'] ) ) {
143 $info['ignored'] = $mangler->mangleList( $info['ignored'] );
144 }
145 if ( isset( $info['optional'] ) ) {
146 $info['optional'] = $mangler->mangleList( $info['optional'] );
147 }
148 }
149
150 $conf['VALIDATORS'] = [
151 [ 'id' => 'BraceBalance' ],
152 [ 'id' => 'MediaWikiLink' ],
153 [ 'id' => 'MediaWikiPageName' ],
154 [ 'id' => 'MediaWikiParameter' ],
155 [ 'id' => 'MediaWikiPlural' ],
156 ];
157
158 $conf['INSERTABLES'] = [
159 [ 'class' => MediaWikiInsertablesSuggester::class ]
160 ];
161
162 if ( isset( $info['optional'] ) ) {
163 $conf['TAGS']['optional'] = $info['optional'];
164 }
165 if ( isset( $info['ignored'] ) ) {
166 $conf['TAGS']['ignored'] = $info['ignored'];
167 }
168
169 if ( isset( $info['languages'] ) ) {
170 $conf['LANGUAGES'] = [
171 'include' => [],
172 'exclude' => [],
173 ];
174
175 foreach ( $info['languages'] as $tagSpec ) {
176 if ( preg_match( '/^([+-])?(.+)$/', $tagSpec, $m ) ) {
177 list( , $sign, $tag ) = $m;
178 if ( $sign === '+' ) {
179 $conf['LANGUAGES']['include'][] = $tag;
180 } elseif ( $sign === '-' ) {
181 $conf['LANGUAGES']['exclude'][] = $tag;
182 } else {
183 $conf['LANGUAGES']['exclude'] = '*';
184 $conf['LANGUAGES']['include'][] = $tag;
185 }
186 }
187 }
188 }
189
190 // @phan-suppress-next-line PhanTypeMismatchReturnSuperType
191 return MessageGroupBase::factory( $conf );
192 }
193
194 protected function parseFile() {
195 $defines = file_get_contents( $this->definitionFile );
196 $linefeed = '(\r\n|\n)';
197 $sections = array_map(
198 'trim',
199 preg_split( "/$linefeed{2,}/", $defines, -1, PREG_SPLIT_NO_EMPTY )
200 );
201 $groups = [];
202
203 foreach ( $sections as $section ) {
204 $lines = array_map( 'trim', preg_split( "/$linefeed/", $section ) );
205 $newgroup = [];
206
207 foreach ( $lines as $line ) {
208 if ( $line === '' || $line[0] === '#' ) {
209 continue;
210 }
211
212 if ( strpos( $line, '=' ) === false ) {
213 if ( empty( $newgroup['name'] ) ) {
214 $newgroup['name'] = $line;
215 } else {
216 throw new MWException( 'Trying to define name twice: ' . $line );
217 }
218 } else {
219 list( $key, $value ) = array_map( 'trim', explode( '=', $line, 2 ) );
220 switch ( $key ) {
221 case 'aliasfile':
222 case 'desc':
223 case 'descmsg':
224 case 'file':
225 case 'id':
226 case 'magicfile':
227 case 'var':
228 $newgroup[$key] = $value;
229 break;
230 case 'optional':
231 case 'ignored':
232 case 'languages':
233 $values = array_map( 'trim', explode( ',', $value ) );
234 if ( !isset( $newgroup[$key] ) ) {
235 $newgroup[$key] = [];
236 }
237 $newgroup[$key] = array_merge( $newgroup[$key], $values );
238 break;
239 case 'prefix':
240 list( $prefix, $messages ) = array_map(
241 'trim',
242 explode( '|', $value, 2 )
243 );
244 if ( isset( $newgroup['prefix'] ) && $newgroup['prefix'] !== $prefix ) {
245 throw new MWException(
246 "Only one prefix supported: {$newgroup['prefix']} !== $prefix"
247 );
248 }
249 $newgroup['prefix'] = $prefix;
250
251 if ( !isset( $newgroup['mangle'] ) ) {
252 $newgroup['mangle'] = [];
253 }
254
255 $messages = array_map( 'trim', explode( ',', $messages ) );
256 $newgroup['mangle'] = array_merge( $newgroup['mangle'], $messages );
257 break;
258 default:
259 throw new MWException( 'Unknown key:' . $key );
260 }
261 }
262 }
263
264 if ( count( $newgroup ) ) {
265 if ( empty( $newgroup['name'] ) ) {
266 throw new MWException( "Name missing\n" . print_r( $newgroup, true ) );
267 }
268 $groups[] = $newgroup;
269 }
270 }
271
272 return $groups;
273 }
274
275 protected function processGroups( $groups ) {
276 $fixedGroups = [];
277 foreach ( $groups as $g ) {
278 $name = $g['name'];
279
280 $id = $g['id'] ?? $this->idPrefix . preg_replace( '/\s+/', '', strtolower( $name ) );
281
282 if ( !isset( $g['file'] ) ) {
283 $file = preg_replace( '/\s+/', '', "$name/i18n/%CODE%.json" );
284 } else {
285 $file = $g['file'];
286 }
287
288 $descmsg = $g['descmsg'] ?? str_replace( $this->idPrefix, '', $id ) . '-desc';
289
290 $newgroup = [
291 'name' => $name,
292 'file' => $file,
293 'descmsg' => $descmsg,
294 ];
295
296 $copyvars = [
297 'aliasfile',
298 'desc',
299 'ignored',
300 'languages',
301 'magicfile',
302 'mangle',
303 'optional',
304 'prefix',
305 'var',
306 ];
307
308 foreach ( $copyvars as $var ) {
309 if ( isset( $g[$var] ) ) {
310 $newgroup[$var] = $g[$var];
311 }
312 }
313
314 // Mark some fixed form optional messages automatically
315 if ( !isset( $newgroup['optional' ] ) ) {
316 $newgroup['optional'] = [];
317 }
318
319 // Mark extension name and skin names optional.
320 $newgroup['optional'][] = '*-extensionname';
321 $newgroup['optional'][] = 'skinname-*';
322
323 $fixedGroups[$id] = $newgroup;
324 }
325
326 return $fixedGroups;
327 }
328}
The versatile default implementation of StringMangler interface.
Class which handles special definition format for MediaWiki extensions and skins.
createMessageGroup( $id, $info)
Creates MediaWikiExtensionMessageGroup objects from parsed data.
setGroupPrefix( $value)
How to prefix message group ids.
setNamespace( $value)
Which namespace holds the messages.