MediaWiki  1.23.12
generateJsonI18n.php
Go to the documentation of this file.
1 <?php
2 
28 require_once __DIR__ . '/Maintenance.php';
29 
36  public function __construct() {
37  parent::__construct();
38  $this->mDescription = "Build JSON messages files from a PHP messages file";
39  $this->addArg( 'phpfile', 'PHP file defining a $messages array', true );
40  $this->addArg( 'jsondir', 'Directory to write JSON files to. ' .
41  'Required unless <phpfile> exists and --shim-only is specified', false );
42  $this->addOption( 'langcode', 'Language code; only needed for converting core i18n files',
43  false, true );
44  $this->addOption( 'shim-only', 'Only create or update the backward-compatibility shim' );
45  }
46 
47  public function execute() {
48  $phpfile = $this->getArg( 0 );
49  $jsondir = $this->getArg( 1 );
50 
51  if ( $this->hasOption( 'shim-only' ) ) {
52  $this->shimOnly( $phpfile, $jsondir );
53  return;
54  }
55 
56  if ( $jsondir === null ) {
57  $this->error( 'Argument [jsondir] is required unless --shim-only is specified.' );
58  $this->maybeHelp( true );
59  }
60 
61  if ( !is_readable( $phpfile ) ) {
62  $this->error( "Error reading $phpfile\n", 1 );
63  }
64  include $phpfile;
65  $phpfileContents = file_get_contents( $phpfile );
66 
67  if ( !isset( $messages ) ) {
68  $this->error( "PHP file $phpfile does not define \$messages array\n", 1 );
69  }
70 
71  $extensionStyle = true;
72  if ( !isset( $messages['en'] ) || !is_array( $messages['en'] ) ) {
73  if ( !$this->hasOption( 'langcode' ) ) {
74  $this->error( "PHP file $phpfile does not set language codes, --langcode " .
75  "is required.\n", 1 );
76  }
77  $extensionStyle = false;
78  $langcode = $this->getOption( 'langcode' );
79  $messages = array( $langcode => $messages );
80  } elseif ( $this->hasOption( 'langcode' ) ) {
81  $this->output( "Warning: --langcode option set but will not be used.\n" );
82  }
83 
84  foreach ( $messages as $langcode => $langmsgs ) {
85  $authors = $this->getAuthorsFromComment( $this->findCommentBefore(
86  $extensionStyle ? "\$messages['$langcode'] =" : '$messages =',
87  $phpfileContents
88  ) );
89  // Make sure the @metadata key is the first key in the output
90  $langmsgs = array_merge(
91  array( '@metadata' => array( 'authors' => $authors ) ),
92  $langmsgs
93  );
94 
95  $jsonfile = "$jsondir/$langcode.json";
96  $success = file_put_contents(
97  $jsonfile,
98  FormatJson::encode( $langmsgs, "\t", FormatJson::ALL_OK ) . "\n"
99  );
100  if ( $success === false ) {
101  $this->error( "FAILED to write $jsonfile", 1 );
102  }
103  $this->output( "$jsonfile\n" );
104  }
105 
106  if ( !$this->hasOption( 'langcode' ) ) {
107  $shim = $this->doShim( $jsondir );
108  file_put_contents( $phpfile, $shim );
109  }
110 
111  $this->output( "All done.\n" );
112  $this->output( "Also add \$wgMessagesDirs['YourExtension'] = __DIR__ . '/i18n';\n" );
113  }
114 
115  protected function shimOnly( $phpfile, $jsondir ) {
116  if ( file_exists( $phpfile ) ) {
117  if ( !is_readable( $phpfile ) ) {
118  $this->error( "Error reading $phpfile\n", 1 );
119  }
120 
121  $phpfileContents = file_get_contents( $phpfile );
122  $m = array();
123  if ( !preg_match( '!"/([^"$]+)/\$csCode.json";!', $phpfileContents, $m ) ) {
124  $this->error( "Cannot recognize $phpfile as a shim.\n", 1 );
125  }
126 
127  if ( $jsondir === null ) {
128  $jsondir = $m[1];
129  }
130 
131  $this->output( "Updating existing shim $phpfile\n" );
132  } elseif ( $jsondir === null ) {
133  $this->error( "$phpfile does not exist.\n" .
134  "Argument [jsondir] is required in order to create a new shim.\n", 1 );
135  } else {
136  $this->output( "Creating new shim $phpfile\n" );
137  }
138 
139  $shim = $this->doShim( $jsondir );
140  file_put_contents( $phpfile, $shim );
141  $this->output( "All done.\n" );
142  }
143 
144  protected function doShim( $jsondir ) {
145  $shim = <<<'PHP'
146 <?php
158 $messages = array();
159 if ( !function_exists( '{{FUNC}}' ) ) {
160  function {{FUNC}}( $cache, $code, &$cachedData ) {
161  $codeSequence = array_merge( array( $code ), $cachedData['fallbackSequence'] );
162  foreach ( $codeSequence as $csCode ) {
163  $fileName = dirname( __FILE__ ) . "/{{OUT}}/$csCode.json";
164  if ( is_readable( $fileName ) ) {
165  $data = FormatJson::decode( file_get_contents( $fileName ), true );
166  foreach ( array_keys( $data ) as $key ) {
167  if ( $key === '' || $key[0] === '@' ) {
168  unset( $data[$key] );
169  }
170  }
171  $cachedData['messages'] = array_merge( $data, $cachedData['messages'] );
172  }
173 
174  $cachedData['deps'][] = new FileDependency( $fileName );
175  }
176  return true;
177  }
178 
179  $GLOBALS['wgHooks']['LocalisationCacheRecache'][] = '{{FUNC}}';
180 }
181 
182 PHP;
183 
184  $jsondir = str_replace( '\\', '/', $jsondir );
185  $shim = str_replace( '{{OUT}}', $jsondir, $shim );
186  $shim = str_replace( '{{FUNC}}', 'wfJsonI18nShim' . wfRandomString( 16 ), $shim );
187  return $shim;
188  }
189 
196  protected function findCommentBefore( $needle, $haystack ) {
197  $needlePos = strpos( $haystack, $needle );
198  if ( $needlePos === false ) {
199  return '';
200  }
201  // Need to pass a negative offset to strrpos() so it'll search backwards from the
202  // offset
203  $startPos = strrpos( $haystack, '
216  protected function getAuthorsFromComment( $comment ) {
217  $matches = null;
218  preg_match_all( '/@author (.*?)$/m', $comment, $matches );
219  return $matches && $matches[1] ? $matches[1] : array();
220  }
221 }
222 
223 $maintClass = "GenerateJsonI18n";
224 require_once RUN_MAINTENANCE_IF_MAIN;
FileDependency
Definition: CacheDependency.php:151
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
GenerateJsonI18n\__construct
__construct()
Default constructor.
Definition: generateJsonI18n.php:36
PHP
The ContentHandler facility adds support for arbitrary content types on wiki instead of relying on wikitext for everything It was introduced in MediaWiki Each kind of and so on Built in content types as usual *javascript user provided javascript code *css user provided css code *text plain text In PHP
Definition: contenthandler.txt:5
Maintenance\maybeHelp
maybeHelp( $force=false)
Maybe show the help.
Definition: Maintenance.php:710
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false)
Add a parameter to the script.
Definition: Maintenance.php:169
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: maintenance.txt:39
$messages
$messages
Definition: LogTests.i18n.php:8
FormatJson\ALL_OK
const ALL_OK
Skip escaping as many characters as reasonably possible.
Definition: FormatJson.php:55
FormatJson\decode
static decode( $value, $assoc=false)
Decodes a JSON string.
Definition: FormatJson.php:126
FormatJson\encode
static encode( $value, $pretty=false, $escaping=0)
Returns the JSON representation of a value.
Definition: FormatJson.php:104
$success
$success
Definition: Utf8Test.php:91
GenerateJsonI18n\execute
execute()
Do the actual work.
Definition: generateJsonI18n.php:47
GenerateJsonI18n\getAuthorsFromComment
getAuthorsFromComment( $comment)
Get an array of author names from a documentation comment containing.
Definition: generateJsonI18n.php:206
GenerateJsonI18n\doShim
doShim( $jsondir)
Definition: generateJsonI18n.php:144
GenerateJsonI18n
Maintenance script to generate JSON i18n files from a PHP i18n file.
Definition: generateJsonI18n.php:35
GenerateJsonI18n\findCommentBefore
findCommentBefore( $needle, $haystack)
Find the documentation comment immediately before a given search string.
Definition: generateJsonI18n.php:186
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
GenerateJsonI18n\shimOnly
shimOnly( $phpfile, $jsondir)
Definition: generateJsonI18n.php:115
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:191
$cache
$cache
Definition: mcc.php:32
Maintenance\addArg
addArg( $arg, $description, $required=true)
Add some args that are needed.
Definition: Maintenance.php:207
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
Maintenance\error
error( $err, $die=0)
Throw an error to the user.
Definition: Maintenance.php:333
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:314
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular param exists.
Definition: Maintenance.php:181
Maintenance\getArg
getArg( $argId=0, $default=null)
Get an argument.
Definition: Maintenance.php:246
$GLOBALS
$GLOBALS['IP']
Definition: ComposerHookHandler.php:6
wfRandomString
wfRandomString( $length=32)
Get a random string containing a number of pseudo-random hex characters.
Definition: GlobalFunctions.php:347