00001 <?php
00012 class MessageWriter {
00013 static $optionalComment = 'only translate this message to other languages if you have to change it';
00014 static $ignoredComment = "do not translate or duplicate this message to other languages";
00015
00016 static $messageStructure;
00017 static $blockComments;
00018 static $messageComments;
00019 static $ignoredMessages;
00020 static $optionalMessages;
00021
00030 public static function writeMessagesToFile( $messages, $code, $write, $listUnknown, $removeUnknown ) {
00031 # Rewrite the messages array
00032 $messages = self::writeMessagesArray( $messages, $code == 'en', false, $removeUnknown );
00033 $messagesText = $messages[0];
00034 $sortedMessages = $messages[1];
00035
00036 # Write to the file
00037 $filename = Language::getMessagesFileName( $code );
00038 $contents = file_get_contents( $filename );
00039 if( strpos( $contents, '$messages' ) !== false ) {
00040 $contents = explode( '$messages', $contents );
00041 if( $messagesText == '$messages' . $contents[1] ) {
00042 echo "Generated messages for language $code. Same as the current file.\n";
00043 } else {
00044 if( $write ) {
00045 $new = $contents[0];
00046 $new .= $messagesText;
00047 file_put_contents( $filename, $new );
00048 echo "Generated and wrote messages for language $code.\n";
00049 } else {
00050 echo "Generated messages for language $code. Please run the script again (without the parameter \"dry-run\") to write the array to the file.\n";
00051 }
00052 }
00053 if( $listUnknown && isset( $sortedMessages['unknown'] ) && !empty( $sortedMessages['unknown'] ) ) {
00054 if ( $removeUnknown )
00055 echo "\nThe following " . count( $sortedMessages['unknown'] ) . " unknown messages have been removed:\n";
00056 else
00057 echo "\nThere are " . count( $sortedMessages['unknown'] ) . " unknown messages, please check them:\n";
00058 foreach( $sortedMessages['unknown'] as $key => $value ) {
00059 echo "* " . $key . "\n";
00060 }
00061 }
00062 } else {
00063 echo "Generated messages for language $code. There seem to be no messages array in the file.\n";
00064 }
00065 }
00066
00075 public static function writeMessagesArray( $messages, $ignoredComments = false, $prefix = false, $removeUnknown = false ) {
00076 # Load messages
00077 $dir = $prefix ? $prefix : dirname( __FILE__ );
00078
00079 require( $dir . '/messages.inc' );
00080 self::$messageStructure = $wgMessageStructure;
00081 self::$blockComments = $wgBlockComments;
00082 self::$messageComments = $wgMessageComments;
00083
00084 require( $dir . '/messageTypes.inc' );
00085 self::$ignoredMessages = $wgIgnoredMessages;
00086 self::$optionalMessages = $wgOptionalMessages;
00087
00088
00089 # Sort messages to blocks
00090 $sortedMessages['unknown'] = $messages;
00091 foreach( self::$messageStructure as $blockName => $block ) {
00092 foreach( $block as $key ) {
00093 if( array_key_exists( $key, $sortedMessages['unknown'] ) ) {
00094 $sortedMessages[$blockName][$key] = $sortedMessages['unknown'][$key];
00095 unset( $sortedMessages['unknown'][$key] );
00096 }
00097 }
00098 }
00099
00100 # Write all the messages
00101 $messagesText = "\$messages = array(
00102 ";
00103 foreach( $sortedMessages as $block => $messages ) {
00104 # Skip if it's the block of unknown messages - handle that in the end of file
00105 if( $block == 'unknown' ) {
00106 continue;
00107 }
00108
00109 if( $ignoredComments ) {
00110 $ignored = self::$ignoredMessages;
00111 $optional = self::$optionalMessages;
00112 } else {
00113 $ignored = array();
00114 $optional = array();
00115 }
00116 $comments = self::makeComments( array_keys($messages), self::$messageComments, $ignored, $optional );
00117
00118 # Write the block
00119 $messagesText .= self::writeMessagesBlock( self::$blockComments[$block], $messages, $comments );
00120 }
00121
00122 # Write the unknown messages, alphabetically sorted.
00123 # Of course, we don't have any comments for them, because they are unknown.
00124 if ( !$removeUnknown ) {
00125 ksort( $sortedMessages['unknown'] );
00126 $messagesText .= self::writeMessagesBlock( 'Unknown messages', $sortedMessages['unknown'] );
00127 }
00128 $messagesText .= ");
00129 ";
00130 return array( $messagesText, $sortedMessages );
00131 }
00132
00141 public static function makeComments( $messages, $comments, $ignored, $optional ) {
00142 # Comment collector
00143 $commentArray = array();
00144
00145 # List of keys only
00146 foreach( $messages as $key ) {
00147 $commentsForKey = array();
00148
00149 # Add descriptive comment for this message if there is one
00150 if( array_key_exists( $key, $comments ) ) {
00151 $commentsForKey[] = $comments[$key];
00152 }
00153
00154 # For translator information only
00155 if( in_array( $key, $ignored ) ) {
00156 $commentsForKey[] = self::$ignoredComment;
00157 } elseif( in_array( $key, $optional ) ) {
00158 $commentsForKey[] = self::$optionalComment;
00159 }
00160
00161 # Format one or more comments nicely and store in array
00162 if( count( $commentsForKey ) ) {
00163 $commentArray[$key] = ' # ' . implode( '; ', $commentsForKey );
00164 }
00165 }
00166
00167 return $commentArray;
00168 }
00169
00180 public static function writeMessagesBlock( $blockComment, $messages,
00181 $messageComments = array(), $prefix = '' ) {
00182
00183 $blockText = '';
00184
00185 # Skip the block if it includes no messages
00186 if( empty( $messages ) ) {
00187 return '';
00188 }
00189
00190 # Format the block comment (if exists); check for multiple lines comments
00191 if( !empty( $blockComment ) ) {
00192 if( strpos( $blockComment, "\n" ) === false ) {
00193 $blockText .= "$prefix# $blockComment
00194 ";
00195 } else {
00196 $blockText .= "$prefix/*
00197 $blockComment
00198 */
00199 ";
00200 }
00201 }
00202
00203 # Get max key length
00204 $maxKeyLength = max( array_map( 'strlen', array_keys( $messages ) ) );
00205
00206 # Format the messages
00207 foreach( $messages as $key => $value ) {
00208 # Add the key name
00209 $blockText .= "$prefix'$key'";
00210
00211 # Add the appropriate block whitespace
00212 $blockText .= str_repeat( ' ', $maxKeyLength - strlen( $key ) );
00213
00214 # Refer to the value
00215 $blockText .= ' => ';
00216
00217 # Check for the appropriate apostrophe and add the value
00218 # Quote \ here, because it needs always escaping
00219 $value = addcslashes( $value, '\\' );
00220
00221 # For readability
00222 $single = "'";
00223 $double = '"';
00224
00225 if( strpos( $value, $single ) === false ) {
00226 # Nothing ugly, just use '
00227 $blockText .= $single.$value.$single;
00228 } elseif( strpos( $value, $double ) === false && !preg_match('/\$[a-zA-Z_\x7f-\xff]/', $value) ) {
00229 # No "-quotes, no variables that need quoting, use "
00230 $blockText .= $double.$value.$double;
00231 } else {
00232 # Something needs quoting, pick the quote which causes less quoting
00233 $quote = substr_count( $value, $double ) + substr_count( $value, '$' ) >= substr_count( $value, $single ) ? $single : $double;
00234 if( $quote === $double ) {
00235 $extra = '$';
00236 } else {
00237 $extra = '';
00238 }
00239 $blockText .= $quote . addcslashes( $value, $quote . $extra ) . $quote;
00240 }
00241
00242 # Comma
00243 $blockText .= ',';
00244
00245 # Add comments, if there is any
00246 if( array_key_exists( $key, $messageComments ) ) {
00247 $blockText .= $messageComments[$key];
00248 }
00249
00250 # Newline
00251 $blockText .= "
00252 ";
00253 }
00254
00255 # Newline to end the block
00256 $blockText .= "
00257 ";
00258
00259 return $blockText;
00260 }
00261 }