MediaWiki master
importExtensionMessages.php
Go to the documentation of this file.
1<?php
2
5
6require_once __DIR__ . '/../Maintenance.php';
7
9 private $extensionDir;
10 private $extName;
11 private $excludedMsgs;
12 private $outDir;
13 private $coreDataCache;
14
15 public function __construct() {
16 parent::__construct();
17 $this->addArg( 'extension', 'The extension name' );
18 $this->addOption( 'outdir',
19 'The output directory, default $IP/languages/i18n', false, true );
20 }
21
22 public function execute() {
23 $this->init();
24
25 $this->outDir = $this->getOption( 'outdir', MW_INSTALL_PATH . '/languages/i18n' );
26 if ( !file_exists( $this->outDir ) ) {
27 mkdir( $this->outDir, 0777, true );
28 }
29
30 $this->extName = $this->getArg();
31 $extJsonPath = $this->extensionDir . "/{$this->extName}/extension.json";
32 $extJson = file_get_contents( $extJsonPath );
33 if ( $extJson === false ) {
34 $this->fatalError( "Unable to open \"$extJsonPath\"" );
35 }
36 $extData = json_decode( $extJson, JSON_THROW_ON_ERROR );
37
38 $this->excludedMsgs = [];
39 foreach ( [ 'namemsg', 'descriptionmsg' ] as $key ) {
40 if ( isset( $extData[$key] ) ) {
41 $this->excludedMsgs[] = $extData[$key];
42 }
43 }
44
45 foreach ( $this->getMessagesDirs( $extData ) as $dir ) {
46 $this->processDir( $dir );
47 }
48 }
49
50 private function init() {
51 $services = $this->getServiceContainer();
52 $config = $services->getMainConfig();
53 $this->extensionDir = $config->get( MainConfigNames::ExtensionDirectory );
54 }
55
56 private function getMessagesDirs( $extData ) {
57 if ( isset( $extData['MessagesDirs'] ) ) {
58 $messagesDirs = [];
59 foreach ( $extData['MessagesDirs'] as $dirs ) {
60 if ( is_array( $dirs ) ) {
61 foreach ( $dirs as $dir ) {
62 $messagesDirs[] = $dir;
63 }
64 } else {
65 $messagesDirs[] = $dirs;
66 }
67 }
68 } else {
69 $messagesDirs = [ 'i18n' ];
70 }
71 return $messagesDirs;
72 }
73
74 private function processDir( $dir ) {
75 $path = $this->extensionDir . "/{$this->extName}/$dir";
76
77 foreach ( new DirectoryIterator( $path ) as $file ) {
78 if ( !$file->isDot() && str_ends_with( $file->getFilename(), '.json' ) ) {
79 $this->processFile(
80 substr( $file->getFilename(), 0, -5 ),
81 $file->getPathname()
82 );
83 }
84 }
85 }
86
87 private function processFile( $lang, $extI18nPath ) {
88 $extJson = file_get_contents( $extI18nPath );
89 if ( $extJson === false ) {
90 $this->error( "Unable to read i18n file \"$extI18nPath\"" );
91 return;
92 }
93 $extData = json_decode( $extJson, JSON_THROW_ON_ERROR );
94 $coreData = $this->getCoreData( $lang );
95
96 if ( isset( $extData['@metadata']['authors'] ) ) {
97 $authors = array_unique( array_merge(
98 $coreData['@metadata']['authors'] ?? [],
99 $extData['@metadata']['authors']
100 ) );
101 // Fix numeric authors
102 foreach ( $authors as &$author ) {
103 $author = (string)$author;
104 }
105 sort( $authors );
106 $coreData['@metadata']['authors'] = $authors;
107 }
108
109 foreach ( $extData as $name => $value ) {
110 if ( str_starts_with( $name, '@' ) ) {
111 continue;
112 }
113 if ( in_array( $name, $this->excludedMsgs ) ) {
114 continue;
115 }
116 $coreData[$name] = $value;
117 }
118
119 $this->setCoreData( $lang, $coreData );
120 }
121
122 private function getCoreData( $lang ) {
123 if ( !isset( $this->coreDataCache[$lang] ) ) {
124 $corePath = MW_INSTALL_PATH . "/languages/i18n/$lang.json";
125 // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
126 $coreJson = @file_get_contents( $corePath );
127 if ( $coreJson === false ) {
128 $this->error( "Warning: discarding extension localisation " .
129 "for language \"$lang\" not present in core" );
130 // Do not write to coreDataCache -- suppress creation of the core file.
131 return [];
132 }
133 $this->coreDataCache[$lang] = json_decode( $coreJson, JSON_THROW_ON_ERROR );
134 }
135 return $this->coreDataCache[$lang];
136 }
137
138 private function setCoreData( $lang, $data ) {
139 if ( !isset( $this->coreDataCache[$lang] ) ) {
140 // Non-existent file, do not create
141 return;
142 }
143
144 $this->coreDataCache[$lang] = $data;
145 $outPath = "{$this->outDir}/$lang.json";
146 if ( !file_put_contents(
147 $outPath,
148 FormatJson::encode( $data, "\t", FormatJson::ALL_OK ) . "\n"
149 ) ) {
150 $this->error( "Unable to write core i18n file \"$outPath\"" );
151 }
152 }
153}
154
155$maintClass = ImportExtensionMessages::class;
156require_once RUN_MAINTENANCE_IF_MAIN;
__construct()
Default constructor.
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
error( $err, $die=0)
Throw an error to the user.
addArg( $arg, $description, $required=true, $multi=false)
Add some args that are needed.
getServiceContainer()
Returns the main service container.
getArg( $argId=0, $default=null)
Get an argument.
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
getOption( $name, $default=null)
Get an option, or return the default.
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
JSON formatter wrapper class.
A class containing constants representing the names of configuration variables.