diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2006-10-11 20:21:25 +0000 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2006-10-11 20:21:25 +0000 |
commit | d81f562b712f2387fa02290bf2ca86392ab356f2 (patch) | |
tree | d666cdefbe6ac320827a2c6cb473581b46e22c4c /maintenance/language | |
parent | 183851b06bd6c52f3cae5375f433da720d410447 (diff) |
Aktualisierung auf Version 1.8.1
Diffstat (limited to 'maintenance/language')
-rw-r--r-- | maintenance/language/alltrans.php | 16 | ||||
-rw-r--r-- | maintenance/language/checkLanguage.php | 177 | ||||
-rw-r--r-- | maintenance/language/checktrans.php | 44 | ||||
-rw-r--r-- | maintenance/language/date-formats.php | 45 | ||||
-rw-r--r-- | maintenance/language/diffLanguage.php | 159 | ||||
-rw-r--r-- | maintenance/language/dumpMessages.php | 20 | ||||
-rw-r--r-- | maintenance/language/duplicatetrans.php | 43 | ||||
-rw-r--r-- | maintenance/language/function-list.php | 44 | ||||
-rw-r--r-- | maintenance/language/lang2po.php | 154 | ||||
-rw-r--r-- | maintenance/language/langmemusage.php | 30 | ||||
-rw-r--r-- | maintenance/language/languages.inc | 686 | ||||
-rw-r--r-- | maintenance/language/splitLanguageFiles.inc | 1168 | ||||
-rw-r--r-- | maintenance/language/splitLanguageFiles.php | 13 | ||||
-rw-r--r-- | maintenance/language/transstat.php | 211 | ||||
-rw-r--r-- | maintenance/language/unusedMessages.php | 42 | ||||
-rw-r--r-- | maintenance/language/validate.php | 40 |
16 files changed, 2892 insertions, 0 deletions
diff --git a/maintenance/language/alltrans.php b/maintenance/language/alltrans.php new file mode 100644 index 00000000..f8db9c0d --- /dev/null +++ b/maintenance/language/alltrans.php @@ -0,0 +1,16 @@ +<?php +/** + * @package MediaWiki + * @subpackage Maintenance + * + * Get all the translations messages, as defined in the English language file. + */ + +require_once( dirname(__FILE__).'/../commandLine.inc' ); + +$wgEnglishMessages = array_keys( Language::getMessagesFor( 'en' ) ); +foreach( $wgEnglishMessages as $key ) { + echo "$key\n"; +} + +?> diff --git a/maintenance/language/checkLanguage.php b/maintenance/language/checkLanguage.php new file mode 100644 index 00000000..11c8ec92 --- /dev/null +++ b/maintenance/language/checkLanguage.php @@ -0,0 +1,177 @@ +<?php +/** + * Check a language file. + * + * @package MediaWiki + * @subpackage Maintenance + */ + +require_once( dirname(__FILE__).'/../commandLine.inc' ); +require_once( 'languages.inc' ); + +/** + * Check a language. + * + * @param $code The language code. + */ +function checkLanguage( $code ) { + global $wgLanguages, $wgGeneralMessages, $wgRequiredMessagesNumber, $wgDisplayLevel, $wgLinks, $wgWikiLanguage, $wgChecks; + + # Get messages + $messages = $wgLanguages->getMessages( $code ); + $messagesNumber = count( $messages['translated'] ); + + # Skip the checks if specified + if ( $wgDisplayLevel == 0 ) { + return; + } + + # Untranslated messages + if ( in_array( 'untranslated', $wgChecks ) ) { + $untranslatedMessages = $wgLanguages->getUntranslatedMessages( $code ); + $untranslatedMessagesNumber = count( $untranslatedMessages ); + $wgLanguages->outputMessagesList( $untranslatedMessages, $code, "\n$untranslatedMessagesNumber messages of $wgRequiredMessagesNumber are not translated to $code, but exist in en:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Duplicate messages + if ( in_array( 'duplicate', $wgChecks ) ) { + $duplicateMessages = $wgLanguages->getDuplicateMessages( $code ); + $duplicateMessagesNumber = count( $duplicateMessages ); + $wgLanguages->outputMessagesList( $duplicateMessages, $code, "\n$duplicateMessagesNumber messages of $messagesNumber are translated the same in en and $code:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Obsolete messages + if ( in_array( 'obsolete', $wgChecks ) ) { + $obsoleteMessages = $messages['obsolete']; + $obsoleteMessagesNumber = count( $obsoleteMessages ); + $wgLanguages->outputMessagesList( $obsoleteMessages, $code, "\n$obsoleteMessagesNumber messages of $messagesNumber are not exist in en (or are in the ignored list), but still exist in $code:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Messages without variables + if ( in_array( 'variables', $wgChecks ) ) { + $messagesWithoutVariables = $wgLanguages->getMessagesWithoutVariables( $code ); + $messagesWithoutVariablesNumber = count( $messagesWithoutVariables ); + $wgLanguages->outputMessagesList( $messagesWithoutVariables, $code, "\n$messagesWithoutVariablesNumber messages of $messagesNumber in $code don't use some variables while en uses them:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Empty messages + if ( in_array( 'empty', $wgChecks ) ) { + $emptyMessages = $wgLanguages->getEmptyMessages( $code ); + $emptyMessagesNumber = count( $emptyMessages ); + $wgLanguages->outputMessagesList( $emptyMessages, $code, "\n$emptyMessagesNumber messages of $messagesNumber in $code are empty or -:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Messages with whitespace + if ( in_array( 'whitespace', $wgChecks ) ) { + $messagesWithWhitespace = $wgLanguages->getMessagesWithWhitespace( $code ); + $messagesWithWhitespaceNumber = count( $messagesWithWhitespace ); + $wgLanguages->outputMessagesList( $messagesWithWhitespace, $code, "\n$messagesWithWhitespaceNumber messages of $messagesNumber in $code have a trailing whitespace:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Non-XHTML messages + if ( in_array( 'xhtml', $wgChecks ) ) { + $nonXHTMLMessages = $wgLanguages->getNonXHTMLMessages( $code ); + $nonXHTMLMessagesNumber = count( $nonXHTMLMessages ); + $wgLanguages->outputMessagesList( $nonXHTMLMessages, $code, "\n$nonXHTMLMessagesNumber messages of $messagesNumber in $code are not well-formed XHTML:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } + + # Messages with wrong characters + if ( in_array( 'chars', $wgChecks ) ) { + $messagesWithWrongChars = $wgLanguages->getMessagesWithWrongChars( $code ); + $messagesWithWrongCharsNumber = count( $messagesWithWrongChars ); + $wgLanguages->outputMessagesList( $messagesWithWrongChars, $code, "\n$messagesWithWrongCharsNumber messages of $messagesNumber in $code include hidden chars which should not be used in the messages:", $wgDisplayLevel, $wgLinks, $wgWikiLanguage ); + } +} + +# Show help +if ( isset( $options['help'] ) ) { + echo <<<END +Run this script to check a specific language file, or all of them. +Parameters: + * lang: Language code (default: the installation default language). You can also specify "all" to check all the languages. + * help: Show this help. + * level: Show the following level (default: 2). + * links: Link the message values (default off). + * wikilang: For the links, what is the content language of the wiki to display the output in (default en). + * whitelist: Make only the following checks (form: code,code). + * blacklist: Don't make the following checks (form: code,code). + * duplicate: Additionally check for messages which are translated the same to English (default off). + * noexif: Don't check for EXIF messages (a bit hard and boring to translate), if you know that they are currently not translated and want to focus on other problems (default off). +Check codes (ideally, all of them should result 0; all the checks are executed by default): + * untranslated: Messages which are required to translate, but are not translated. + * obsolete: Messages which are untranslatable, but translated. + * variables: Messages without variables which should be used. + * empty: Empty messages. + * whitespace: Messages which have trailing whitespace. + * xhtml: Messages which are not well-formed XHTML. + * chars: Messages with hidden characters. +Display levels (default: 2): + * 0: Skip the checks (useful for checking syntax). + * 1: Show only the stub headers and number of wrong messages, without list of messages. + * 2: Show only the headers and the message keys, without the message values. + * 3: Show both the headers and the complete messages, with both keys and values. + +END; + exit(); +} + +# Get the language code +if ( isset( $options['lang'] ) ) { + $wgCode = $options['lang']; +} else { + $wgCode = $wgContLang->getCode(); +} + +# Get the display level +if ( isset( $options['level'] ) ) { + $wgDisplayLevel = $options['level']; +} else { + $wgDisplayLevel = 2; +} + +# Get the links options +$wgLinks = isset( $options['links'] ); +$wgWikiLanguage = isset( $options['wikilang'] ) ? $options['wikilang'] : 'en'; + +# Get the checks to do +$wgChecks = array( 'untranslated', 'obsolete', 'variables', 'empty', 'whitespace', 'xhtml', 'chars' ); +if ( isset( $options['whitelist'] ) ) { + $wgChecks = explode( ',', $options['whitelist'] ); +} elseif ( isset( $options['blacklist'] ) ) { + $wgChecks = array_diff( $wgChecks, explode( ',', $options['blacklist'] ) ); +} + +# Add duplicate option if specified +if ( isset( $options['duplicate'] ) ) { + $wgChecks[] = 'duplicate'; +} + +# Should check for EXIF? +$wgCheckEXIF = !isset( $options['noexif'] ); + +# Get language objects +$wgLanguages = new languages( $wgCheckEXIF ); + +# Get the general messages +$wgGeneralMessages = $wgLanguages->getGeneralMessages(); +$wgRequiredMessagesNumber = count( $wgGeneralMessages['required'] ); + +# Check the language +if ( $wgCode == 'all' ) { + foreach ( $wgLanguages->getLanguages() as $language ) { + if ( $language != 'en' && $language != 'enRTL' ) { + checkLanguage( $language ); + } + } +} else { + # Can't check English + if ( $wgCode == 'en' ) { + echo "Current selected language is English, which cannot be checked.\n"; + } else if ( $wgCode == 'enRTL' ) { + echo "Current selected language is RTL English, which cannot be checked.\n"; + } else { + checkLanguage( $wgCode ); + } +} + +?> diff --git a/maintenance/language/checktrans.php b/maintenance/language/checktrans.php new file mode 100644 index 00000000..a5772d47 --- /dev/null +++ b/maintenance/language/checktrans.php @@ -0,0 +1,44 @@ +<?php +/** + * @package MediaWiki + * @subpackage Maintenance + * Check to see if all messages have been translated into the selected language. + * To run this script, you must have a working installation, and you can specify + * a language, or the script will check the installation language. + */ + +/** */ +require_once(dirname(__FILE__).'/../commandLine.inc'); + +if ( isset( $args[0] ) ) { + $code = $args[0]; +} else { + $code = $wgLang->getCode(); +} + +if ( $code == 'en' ) { + print "Current selected language is English. Cannot check translations.\n"; + exit(); +} + +$filename = Language::getMessagesFileName( $code ); +if ( file_exists( $filename ) ) { + require( $filename ); +} else { + $messages = array(); +} + +$count = $total = 0; +$wgEnglishMessages = Language::getMessagesFor( 'en' ); +$wgLocalMessages = $messages; + +foreach ( $wgEnglishMessages as $key => $msg ) { + ++$total; + if ( !isset( $wgLocalMessages[$key] ) ) { + print "'{$key}' => \"$msg\",\n"; + ++$count; + } +} + +print "{$count} messages of {$total} are not translated in the language {$code}.\n"; +?> diff --git a/maintenance/language/date-formats.php b/maintenance/language/date-formats.php new file mode 100644 index 00000000..962c2f8c --- /dev/null +++ b/maintenance/language/date-formats.php @@ -0,0 +1,45 @@ +<?php + +$ts = '20010115123456'; + + +$IP = dirname( __FILE__ ) . '/../..'; +require_once( "$IP/maintenance/commandLine.inc" ); + +foreach ( glob( "$IP/languages/messages/Messages*.php" ) as $filename ) { + $base = basename( $filename ); + if ( !preg_match( '/Messages(.*)\.php$/', $base, $m ) ) { + continue; + } + $code = str_replace( '_', '-', strtolower( $m[1] ) ); + print "$code "; + $lang = Language::factory( $code ); + $prefs = $lang->getDatePreferences(); + if ( !$prefs ) { + $prefs = array( 'default' ); + } + print "date: "; + foreach ( $prefs as $index => $pref ) { + if ( $index > 0 ) { + print ' | '; + } + print $lang->date( $ts, false, $pref ); + } + print "\n$code time: "; + foreach ( $prefs as $index => $pref ) { + if ( $index > 0 ) { + print ' | '; + } + print $lang->time( $ts, false, $pref ); + } + print "\n$code both: "; + foreach ( $prefs as $index => $pref ) { + if ( $index > 0 ) { + print ' | '; + } + print $lang->timeanddate( $ts, false, $pref ); + } + print "\n\n"; +} + +?> diff --git a/maintenance/language/diffLanguage.php b/maintenance/language/diffLanguage.php new file mode 100644 index 00000000..2aaa5902 --- /dev/null +++ b/maintenance/language/diffLanguage.php @@ -0,0 +1,159 @@ +<?php +# MediaWiki web-based config/installation +# Copyright (C) 2004 Ashar Voultoiz <thoane@altern.org> and others +# http://www.mediawiki.org/ +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# http://www.gnu.org/copyleft/gpl.html + +/** + * Usage: php DiffLanguage.php [lang [file]] + * + * lang: Enter the language code following "Language" of the LanguageXX.php you + * want to check. If using linux you might need to follow case aka Zh and not + * zh. + * + * file: A php language file you want to include to compare mediawiki + * Language{Lang}.php against (for example Special:Allmessages PHP output). + * + * The goal is to get a list of messages not yet localised in a languageXX.php + * file using the language.php file as reference. + * + * The script then print a list of wgAllMessagesXX keys that aren't localised, a + * percentage of messages correctly localised and the number of messages to be + * translated. + * + * @package MediaWiki + * @subpackage Maintenance + */ + +/** This script run from the commandline */ +require_once( dirname(__FILE__).'/../parserTests.inc' ); +require_once( dirname(__FILE__).'/../commandLine.inc' ); + +if( isset($options['help']) ) { usage(); wfDie(); } + +$wgLanguageCode = ucfirstlcrest($wgLanguageCode); +/** Language messages we will use as reference. By default 'en' */ +$referenceMessages = $wgAllMessagesEn; +$referenceLanguage = 'En'; +$referenceFilename = 'Language'.$referenceLanguage.'.php'; +/** Language messages we will test. */ +$testMessages = array(); +$testLanguage = ''; +/** whereas we use an external language file */ +$externalRef = false; + +# FUNCTIONS +/** @todo more informations !! */ +function usage() { +echo 'php DiffLanguage.php [lang [file]] [--color=(yes|no|light)]'."\n"; +} + +/** Return a given string with first letter upper case, the rest lowercase */ +function ucfirstlcrest($string) { + return strtoupper(substr($string,0,1)).strtolower(substr($string,1)); +} + +/** + * Return a $wgAllmessages array shipped in MediaWiki + * @param string $languageCode Formated language code + * @return array The MediaWiki default $wgAllMessages array requested + */ +function getMediawikiMessages($languageCode = 'En') { + + $foo = "wgAllMessages$languageCode"; + global $$foo, $wgSkinNamesEn; + + // it might already be loaded in LocalSettings.php + if(!isset($$foo)) { + global $IP; + $langFile = $IP.'/languages/classes/Language'.$languageCode.'.php'; + if (file_exists( $langFile ) ) { + print "Including $langFile\n"; + global $wgNamespaceNamesEn; + include($langFile); + } else wfDie("ERROR: The file $langFile does not exist !\n"); + } + return $$foo; +} + +/** + * Return a $wgAllmessages array in a given file. Language of the array + * need to be given cause we can not detect which language it provides + * @param string $filename Filename of the file containing a message array + * @param string $languageCode Language of the external array + * @return array A $wgAllMessages array from an external file. + */ +function getExternalMessages($filename, $languageCode) { + print "Including external file $filename.\n"; + include($filename); + $foo = "wgAllMessages$languageCode"; + return $$foo; +} + +# MAIN ENTRY +if ( isset($args[0]) ) { + $lang = ucfirstlcrest($args[0],1); + + // eventually against another language file we will use as reference instead + // of the default english language. + if( isset($args[1])) { + // we assume the external file contain an array of messages for the + // lang we are testing + $referenceMessages = getExternalMessages( $args[1], $lang ); + $referenceLanguage = $lang; + $referenceFilename = $args[1]; + $externalRef = true; + } + + // Load datas from MediaWiki + $testMessages = getMediawikiMessages($lang); + $testLanguage = $lang; +} else { + usage(); + wfDie(); +} + +/** parsertest is used to do differences */ +$myParserTest = new ParserTest(); + +# Get all references messages and check if they exist in the tested language +$i = 0; + +$msg = "MW Language{$testLanguage}.php against "; +if($externalRef) { $msg .= 'external file '; } +else { $msg .= 'internal file '; } +$msg .= $referenceFilename.' ('.$referenceLanguage."):\n----\n"; +echo $msg; + +// process messages +foreach($referenceMessages as $index => $ref) +{ + // message is not localized + if(!(isset($testMessages[$index]))) { + $i++; + print "'$index' => \"$ref\",\n"; + // Messages in the same language differs + } elseif( ($lang == $referenceLanguage) AND ($testMessages[$index] != $ref)) { + print "\n$index differs:\n"; + print $myParserTest->quickDiff($testMessages[$index],$ref,'tested','reference'); + } +} + +echo "\n----\n".$msg; +echo "$referenceLanguage language is complete at ".number_format((100 - $i/count($wgAllMessagesEn) * 100),2)."%\n"; +echo "$i unlocalised messages of the ".count($wgAllMessagesEn)." messages available.\n"; +?> diff --git a/maintenance/language/dumpMessages.php b/maintenance/language/dumpMessages.php new file mode 100644 index 00000000..bd7e2aed --- /dev/null +++ b/maintenance/language/dumpMessages.php @@ -0,0 +1,20 @@ +<?php +/** + * @todo document + * @package MediaWiki + * @subpackage Maintenance + */ + +/** */ +require_once( dirname(__FILE__).'/../commandLine.inc' ); +$wgMessageCache->disableTransform(); +$messages = array(); +$wgEnglishMessages = array_keys( Language::getMessagesFor( 'en' ) ); +foreach ( $wgEnglishMessages as $key ) +{ + $messages[$key] = wfMsg( $key ); +} +print "MediaWiki $wgVersion language file\n"; +print serialize( $messages ); + +?> diff --git a/maintenance/language/duplicatetrans.php b/maintenance/language/duplicatetrans.php new file mode 100644 index 00000000..9273ee6e --- /dev/null +++ b/maintenance/language/duplicatetrans.php @@ -0,0 +1,43 @@ +<?php +/** + * Prints out messages that are the same as the message with the corrisponding + * key in the English file + * + * @package MediaWiki + * @subpackage Maintenance + */ + +require_once(dirname(__FILE__).'/../commandLine.inc'); + +if ( isset( $args[0] ) ) { + $code = $args[0]; +} else { + $code = $wgLang->getCode(); +} + +if ( $code == 'en' ) { + print "Current selected language is English. Cannot check translations.\n"; + exit(); +} + +$filename = Language::getMessagesFileName( $code ); +if ( file_exists( $filename ) ) { + require( $filename ); +} else { + $messages = array(); +} + +$count = $total = 0; +$wgEnglishMessages = Language::getMessagesFor( 'en' ); +$wgLocalMessages = $messages; + +foreach ( $wgLocalMessages as $key => $msg ) { + ++$total; + if ( @$wgEnglishMessages[$key] == $msg ) { + echo "* $key\n"; + ++$count; + } +} + +echo "{$count} messages of {$total} are duplicates in the language {$code}\n"; +?> diff --git a/maintenance/language/function-list.php b/maintenance/language/function-list.php new file mode 100644 index 00000000..84efb29d --- /dev/null +++ b/maintenance/language/function-list.php @@ -0,0 +1,44 @@ +<?php + +define( 'MEDIAWIKI', 1 ); +define( 'NOT_REALLY_MEDIAWIKI', 1 ); + +class Language {} +foreach ( glob( 'Language*.php' ) as $file ) { + if ( $file != 'Language.php' ) { + require_once( $file ); + } +} + +$removedFunctions = array( 'date', 'time', 'timeanddate', 'formatMonth', 'formatDay', + 'getMonthName', 'getMonthNameGen', 'getMonthAbbreviation', 'getWeekdayName', + 'userAdjust', 'dateFormat', 'timeSeparator', 'timeDateSeparator', 'timeBeforeDate', + 'monthByLatinNumber', 'getSpecialMonthName', + + 'commafy' +); + +$numRemoved = 0; +$total = 0; +$classes = get_declared_classes(); +ksort( $classes ); +foreach ( $classes as $class ) { + if ( !preg_match( '/^Language/', $class ) || $class == 'Language' || $class == 'LanguageConverter' ) { + continue; + } + + print "$class\n"; + $methods = get_class_methods( $class ); + print_r( $methods ); + + if ( !count( array_diff( $methods, $removedFunctions ) ) ) { + print "removed\n"; + $numRemoved++; + } + $total++; + print "\n"; +} + +print "$numRemoved will be removed out of $total\n"; + +?> diff --git a/maintenance/language/lang2po.php b/maintenance/language/lang2po.php new file mode 100644 index 00000000..520d8d6e --- /dev/null +++ b/maintenance/language/lang2po.php @@ -0,0 +1,154 @@ +<?php +/** + * Convert Language files to .po files ! + * + * Todo: + * - generate .po header + * - fix escaping of \ + */ + +/** This is a command line script */ +require_once(dirname(__FILE__).'/../commandLine.inc'); +require_once(dirname(__FILE__).'/languages.inc'); + +define('ALL_LANGUAGES', true); +define('XGETTEXT_BIN', 'xgettext'); +define('MSGMERGE_BIN', 'msgmerge'); + +// used to generate the .pot +define('XGETTEXT_OPTIONS', '-n --keyword=wfMsg --keyword=wfMsgForContent --keyword=wfMsgHtml --keyword=wfMsgWikiHtml '); +define('MSGMERGE_OPTIONS', ' -v '); + +define('LOCALE_OUTPUT_DIR', $IP.'/locale'); + + +if( isset($options['help']) ) { usage(); wfDie(); } +// default output is WikiText +if( !isset($options['lang']) ) { $options['lang'] = ALL_LANGUAGES; } + +function usage() { +print <<<END +Usage: php lang2po.php [--help] [--lang=<langcode>] [--stdout] + --help: this message. + --lang: a lang code you want to generate a .po for (default: all languages). + +END; +} + + +/** + * Return a dummy header for later edition. + * @return string A dummy header + */ +function poHeader() { +return +'# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2005 MediaWiki +# This file is distributed under the same license as the MediaWiki package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: bugzilllaaaaa\n" +"POT-Creation-Date: 2005-08-16 20:13+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: VARIOUS <nobody>\n" +"Language-Team: LANGUAGE <nobody>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +'; +} + +/** + * generate and write a file in .po format. + * + * @param string $langcode Code of a language it will process. + * @param array &$messages Array containing the various messages. + * @return string Filename where stuff got saved or false. + */ +function generatePo($langcode, &$messages) { + $data = poHeader(); + + // Generate .po entries + foreach($messages as $identifier => $content) { + $data .= "msgid \"$identifier\"\n"; + + // Escape backslashes + $tmp = str_replace('\\', '\\\\', $content); + // Escape doublelquotes + $tmp = preg_replace( "/(?<!\\\\)\"/", '\"', $tmp); + // Rewrite multilines to gettext format + $tmp = str_replace("\n", "\"\n\"", $tmp); + + $data .= 'msgstr "'. $tmp . "\"\n\n"; + } + + // Write the content to a file in locale/XX/messages.po + $dir = LOCALE_OUTPUT_DIR.'/'.$langcode; + if( !is_dir($dir) ) { mkdir( $dir, 0770 ); } + $filename = $dir.'/fromlanguagefile.po'; + + $file = fopen( $filename , 'wb' ); + if( fwrite( $file, $data ) ) { + fclose( $file ); + return $filename; + } else { + fclose( $file ); + return false; + } +} + +function generatePot() { + global $IP; + $curdir = getcwd(); + chdir($IP); + exec( XGETTEXT_BIN + .' '.XGETTEXT_OPTIONS + .' -o '.LOCALE_OUTPUT_DIR.'/wfMsg.pot' + .' includes/*php' + ); + chdir($curdir); +} + +function applyPot($langcode) { + $langdir = LOCALE_OUTPUT_DIR.'/'.$langcode; + + $from = $langdir.'/fromlanguagefile.po'; + $pot = LOCALE_OUTPUT_DIR.'/wfMsg.pot'; + $dest = $langdir.'/messages.po'; + + // Merge template and generate file to get final .po + exec(MSGMERGE_BIN.MSGMERGE_OPTIONS." $from $pot -o $dest "); + // delete no more needed file +// unlink($from); +} + +// Generate a template .pot based on source tree +echo "Getting 'gettext' default messages from sources:"; +generatePot(); +echo "done.\n"; + + +$langTool = new languages(); + +// Do all languages +foreach ( $langTool->getMessages() as $langcode) { + echo "Loading messages for $langcode:\t"; + require_once( Language::getClassFileName( $langcode ) ); + $arr = 'wgAllMessages'.$langcode; + if(!@is_array($$arr)) { + echo "NONE FOUND\n"; + } else { + echo "ok\n"; + if( ! generatePo($langcode, $$arr) ) { + echo "ERROR: Failed to wrote file.\n"; + } else { + echo "Applying template:"; + applyPot($langcode); + } + } +} +?> diff --git a/maintenance/language/langmemusage.php b/maintenance/language/langmemusage.php new file mode 100644 index 00000000..974bb0d8 --- /dev/null +++ b/maintenance/language/langmemusage.php @@ -0,0 +1,30 @@ +<?php +/** + * Dumb program that tries to get the memory usage + * for each language file. + */ + +/** This is a command line script */ +require_once(dirname(__FILE__).'/../commandLine.inc'); +require_once(dirname(__FILE__).'/languages.inc'); + +$langtool = new languages(); + +if ( ! function_exists( 'memory_get_usage' ) ) + wfDie( "You must compile PHP with --enable-memory-limit\n" ); + +$memlast = $memstart = memory_get_usage(); + +print 'Base memory usage: '.$memstart."\n"; + +foreach ( $langtool->getLanguages() as $langcode ) { + require_once( Language::getClassFileName( $langcode ) ); + $memstep = memory_get_usage(); + printf( "%12s: %d\n", $langcode, ($memstep- $memlast) ); + $memlast = $memstep; +} + +$memend = memory_get_usage(); + +echo ' Total Usage: '.($memend - $memstart)."\n"; +?> diff --git a/maintenance/language/languages.inc b/maintenance/language/languages.inc new file mode 100644 index 00000000..86cd0869 --- /dev/null +++ b/maintenance/language/languages.inc @@ -0,0 +1,686 @@ +<?php +/** + * Handle messages in the language files. + * + * @package MediaWiki + * @subpackage Maintenance + */ + +class languages { + private $mLanguages; # List of languages + private $mRawMessages; # Raw list of the messages in each language + private $mMessages; # Messages in each language (except for English), divided to groups + private $mGeneralMessages; # General messages in English, divided to groups + private $mIgnoredMessages = array( + 'sidebar', + 'addsection', + 'anonnotice', + 'catseparator', + 'googlesearch', + 'exif-make-value', + 'exif-model-value', + 'exif-software-value', + 'history_copyright', + 'licenses', + 'loginend', + 'loginlanguagelinks', + 'markaspatrolledlink', + 'newarticletextanon', + 'noarticletextanon', + 'number_of_watching_users_RCview', + 'pubmedurl', + 'randompage-url', + 'recentchanges-url', + 'rfcurl', + 'shareddescriptionfollows', + 'signupend', + 'sitenotice', + 'sitesubtitle', + 'sitetitle', + 'talkpagetext', + 'trackback', + 'trackbackexcerpt', + 'widthheight', + ); # All the messages which should be exist only in the English file + private $mOptionalMessages = array( + 'imgmultigotopost', + 'linkprefix', + 'allpages-summary', + 'booksources-summary', + 'ipblocklist-summary', + 'listusers-summary', + 'longpages-summary', + 'preferences-summary', + 'specialpages-summary', + 'whatlinkshere-summary', + 'whatlinkshere-barrow', + 'imagelist-summary', + 'mimesearch-summary', + 'listredirects-summary', + 'uncategorizedpages-summary', + 'uncategorizedcategories-summary', + 'uncategorizedimages-summary', + 'popularpages-summary', + 'wantedcategories-summary', + 'wantedpages-summary', + 'mostlinked-summary', + 'mostlinkedcategories-summary', + 'mostcategories-summary', + 'mostimages-summary', + 'mostrevisions-summary', + 'prefixindex-summary', + 'shortpages-summary', + 'newpages-summary', + 'ancientpages-summary', + 'newimages-summary', + 'unwatchedpages-summary', + 'userrights-summary', + 'variantname-zh-cn', + 'variantname-zh-tw', + 'variantname-zh-hk', + 'variantname-zh-sg', + 'variantname-zh', + 'variantname-sr-ec', + 'variantname-sr-el', + 'variantname-sr-jc', + 'variantname-sr-jl', + 'variantname-sr', + 'variantname-kk-tr', + 'variantname-kk-kz', + 'variantname-kk-cn', + 'variantname-kk', + ); # All the messages which may be translated or not, depending on the language + private $mEXIFMessages = array( + 'exif-imagewidth', + 'exif-imagelength', + 'exif-bitspersample', + 'exif-compression', + 'exif-photometricinterpretation', + 'exif-orientation', + 'exif-samplesperpixel', + 'exif-planarconfiguration', + 'exif-ycbcrsubsampling', + 'exif-ycbcrpositioning', + 'exif-xresolution', + 'exif-yresolution', + 'exif-resolutionunit', + 'exif-stripoffsets', + 'exif-rowsperstrip', + 'exif-stripbytecounts', + 'exif-jpeginterchangeformat', + 'exif-jpeginterchangeformatlength', + 'exif-transferfunction', + 'exif-whitepoint', + 'exif-primarychromaticities', + 'exif-ycbcrcoefficients', + 'exif-referenceblackwhite', + 'exif-datetime', + 'exif-imagedescription', + 'exif-make', + 'exif-model', + 'exif-software', + 'exif-artist', + 'exif-copyright', + 'exif-exifversion', + 'exif-flashpixversion', + 'exif-colorspace', + 'exif-componentsconfiguration', + 'exif-compressedbitsperpixel', + 'exif-pixelydimension', + 'exif-pixelxdimension', + 'exif-makernote', + 'exif-usercomment', + 'exif-relatedsoundfile', + 'exif-datetimeoriginal', + 'exif-datetimedigitized', + 'exif-subsectime', + 'exif-subsectimeoriginal', + 'exif-subsectimedigitized', + 'exif-exposuretime', + 'exif-exposuretime-format', + 'exif-fnumber', + 'exif-fnumber-format', + 'exif-exposureprogram', + 'exif-spectralsensitivity', + 'exif-isospeedratings', + 'exif-oecf', + 'exif-shutterspeedvalue', + 'exif-aperturevalue', + 'exif-brightnessvalue', + 'exif-exposurebiasvalue', + 'exif-maxaperturevalue', + 'exif-subjectdistance', + 'exif-meteringmode', + 'exif-lightsource', + 'exif-flash', + 'exif-focallength', + 'exif-focallength-format', + 'exif-subjectarea', + 'exif-flashenergy', + 'exif-spatialfrequencyresponse', + 'exif-focalplanexresolution', + 'exif-focalplaneyresolution', + 'exif-focalplaneresolutionunit', + 'exif-subjectlocation', + 'exif-exposureindex', + 'exif-sensingmethod', + 'exif-filesource', + 'exif-scenetype', + 'exif-cfapattern', + 'exif-customrendered', + 'exif-exposuremode', + 'exif-whitebalance', + 'exif-digitalzoomratio', + 'exif-focallengthin35mmfilm', + 'exif-scenecapturetype', + 'exif-gaincontrol', + 'exif-contrast', + 'exif-saturation', + 'exif-sharpness', + 'exif-devicesettingdescription', + 'exif-subjectdistancerange', + 'exif-imageuniqueid', + 'exif-gpsversionid', + 'exif-gpslatituderef', + 'exif-gpslatitude', + 'exif-gpslongituderef', + 'exif-gpslongitude', + 'exif-gpsaltituderef', + 'exif-gpsaltitude', + 'exif-gpstimestamp', + 'exif-gpssatellites', + 'exif-gpsstatus', + 'exif-gpsmeasuremode', + 'exif-gpsdop', + 'exif-gpsspeedref', + 'exif-gpsspeed', + 'exif-gpstrackref', + 'exif-gpstrack', + 'exif-gpsimgdirectionref', + 'exif-gpsimgdirection', + 'exif-gpsmapdatum', + 'exif-gpsdestlatituderef', + 'exif-gpsdestlatitude', + 'exif-gpsdestlongituderef', + 'exif-gpsdestlongitude', + 'exif-gpsdestbearingref', + 'exif-gpsdestbearing', + 'exif-gpsdestdistanceref', + 'exif-gpsdestdistance', + 'exif-gpsprocessingmethod', + 'exif-gpsareainformation', + 'exif-gpsdatestamp', + 'exif-gpsdifferential', + 'exif-compression-1', + 'exif-compression-6', + 'exif-photometricinterpretation-2', + 'exif-photometricinterpretation-6', + 'exif-orientation-1', + 'exif-orientation-2', + 'exif-orientation-3', + 'exif-orientation-4', + 'exif-orientation-5', + 'exif-orientation-6', + 'exif-orientation-7', + 'exif-orientation-8', + 'exif-planarconfiguration-1', + 'exif-planarconfiguration-2', + 'exif-xyresolution-i', + 'exif-xyresolution-c', + 'exif-colorspace-1', + 'exif-colorspace-ffff.h', + 'exif-componentsconfiguration-0', + 'exif-componentsconfiguration-1', + 'exif-componentsconfiguration-2', + 'exif-componentsconfiguration-3', + 'exif-componentsconfiguration-4', + 'exif-componentsconfiguration-5', + 'exif-componentsconfiguration-6', + 'exif-exposureprogram-0', + 'exif-exposureprogram-1', + 'exif-exposureprogram-2', + 'exif-exposureprogram-3', + 'exif-exposureprogram-4', + 'exif-exposureprogram-5', + 'exif-exposureprogram-6', + 'exif-exposureprogram-7', + 'exif-exposureprogram-8', + 'exif-subjectdistance-value', + 'exif-meteringmode-0', + 'exif-meteringmode-1', + 'exif-meteringmode-2', + 'exif-meteringmode-3', + 'exif-meteringmode-4', + 'exif-meteringmode-5', + 'exif-meteringmode-6', + 'exif-meteringmode-255', + 'exif-lightsource-0', + 'exif-lightsource-1', + 'exif-lightsource-2', + 'exif-lightsource-3', + 'exif-lightsource-4', + 'exif-lightsource-9', + 'exif-lightsource-10', + 'exif-lightsource-11', + 'exif-lightsource-12', + 'exif-lightsource-13', + 'exif-lightsource-14', + 'exif-lightsource-15', + 'exif-lightsource-17', + 'exif-lightsource-18', + 'exif-lightsource-19', + 'exif-lightsource-20', + 'exif-lightsource-21', + 'exif-lightsource-22', + 'exif-lightsource-23', + 'exif-lightsource-24', + 'exif-lightsource-255', + 'exif-focalplaneresolutionunit-2', + 'exif-sensingmethod-1', + 'exif-sensingmethod-2', + 'exif-sensingmethod-3', + 'exif-sensingmethod-4', + 'exif-sensingmethod-5', + 'exif-sensingmethod-7', + 'exif-sensingmethod-8', + 'exif-filesource-3', + 'exif-scenetype-1', + 'exif-customrendered-0', + 'exif-customrendered-1', + 'exif-exposuremode-0', + 'exif-exposuremode-1', + 'exif-exposuremode-2', + 'exif-whitebalance-0', + 'exif-whitebalance-1', + 'exif-scenecapturetype-0', + 'exif-scenecapturetype-1', + 'exif-scenecapturetype-2', + 'exif-scenecapturetype-3', + 'exif-gaincontrol-0', + 'exif-gaincontrol-1', + 'exif-gaincontrol-2', + 'exif-gaincontrol-3', + 'exif-gaincontrol-4', + 'exif-contrast-0', + 'exif-contrast-1', + 'exif-contrast-2', + 'exif-saturation-0', + 'exif-saturation-1', + 'exif-saturation-2', + 'exif-sharpness-0', + 'exif-sharpness-1', + 'exif-sharpness-2', + 'exif-subjectdistancerange-0', + 'exif-subjectdistancerange-1', + 'exif-subjectdistancerange-2', + 'exif-subjectdistancerange-3', + 'exif-gpslatitude-n', + 'exif-gpslatitude-s', + 'exif-gpslongitude-e', + 'exif-gpslongitude-w', + 'exif-gpsstatus-a', + 'exif-gpsstatus-v', + 'exif-gpsmeasuremode-2', + 'exif-gpsmeasuremode-3', + 'exif-gpsspeed-k', + 'exif-gpsspeed-m', + 'exif-gpsspeed-n', + 'exif-gpsdirection-t', + 'exif-gpsdirection-m', + ); # All the EXIF messages, may be set as optional if defined as such + + /** + * Load the list of languages: all the Messages*.php + * files in the languages directory. + * + * @param $exif Treat the EXIF messages? + */ + function __construct( $exif = true ) { + $this->mLanguages = array_keys( Language::getLanguageNames( true ) ); + sort( $this->mLanguages ); + if ( !$exif ) { + $this->mOptionalMessages = array_merge( $this->mOptionalMessages, $this->mEXIFMessages ); + } + } + + /** + * Get the language list. + * + * @return The language list. + */ + public function getLanguages() { + return $this->mLanguages; + } + + /** + * Load the raw messages for a specific langauge from the messages file. + * + * @param $code The langauge code. + */ + private function loadRawMessages( $code ) { + if ( isset( $this->mRawMessages[$code] ) ) { + return; + } + $filename = Language::getMessagesFileName( $code ); + if ( file_exists( $filename ) ) { + require( $filename ); + if ( isset( $messages ) ) { + $this->mRawMessages[$code] = $messages; + } else { + $this->mRawMessages[$code] = array(); + } + } else { + $this->mRawMessages[$code] = array(); + } + } + + /** + * Load the messages for a specific language (which is not English) and divide them to groups: + * all - all the messages. + * required - messages which should be translated in order to get a complete translation. + * optional - messages which can be translated, the fallback translation is used if not translated. + * obsolete - messages which should not be translated, either because they are not exist, or they are ignored messages. + * translated - messages which are either required or optional, but translated from English and needed. + * + * @param $code The language code. + */ + private function loadMessages( $code ) { + if ( isset( $this->mMessages[$code] ) ) { + return; + } + $this->loadRawMessages( $code ); + $this->loadGeneralMessages(); + $this->mMessages[$code]['all'] = $this->mRawMessages[$code]; + $this->mMessages[$code]['required'] = array(); + $this->mMessages[$code]['optional'] = array(); + $this->mMessages[$code]['obsolete'] = array(); + $this->mMessages[$code]['translated'] = array(); + foreach ( $this->mMessages[$code]['all'] as $key => $value ) { + if ( isset( $this->mGeneralMessages['required'][$key] ) ) { + $this->mMessages[$code]['required'][$key] = $value; + $this->mMessages[$code]['translated'][$key] = $value; + } else if ( isset( $this->mGeneralMessages['optional'][$key] ) ) { + $this->mMessages[$code]['optional'][$key] = $value; + $this->mMessages[$code]['translated'][$key] = $value; + } else { + $this->mMessages[$code]['obsolete'][$key] = $value; + } + } + } + + /** + * Load the messages for English and divide them to groups: + * all - all the messages. + * required - messages which should be translated to other languages in order to get a complete translation. + * optional - messages which can be translated to other languages, but it's not required for a complete translation. + * ignored - messages which should not be translated to other languages. + * translatable - messages which are either required or optional, but can be translated from English. + */ + private function loadGeneralMessages() { + if ( isset( $this->mGeneralMessages ) ) { + return; + } + $this->loadRawMessages( 'en' ); + $this->mGeneralMessages['all'] = $this->mRawMessages['en']; + $this->mGeneralMessages['required'] = array(); + $this->mGeneralMessages['optional'] = array(); + $this->mGeneralMessages['ignored'] = array(); + $this->mGeneralMessages['translatable'] = array(); + foreach ( $this->mGeneralMessages['all'] as $key => $value ) { + if ( in_array( $key, $this->mIgnoredMessages ) ) { + $this->mGeneralMessages['ignored'][$key] = $value; + } else if ( in_array( $key, $this->mOptionalMessages ) ) { + $this->mGeneralMessages['optional'][$key] = $value; + $this->mGeneralMessages['translatable'][$key] = $value; + } else { + $this->mGeneralMessages['required'][$key] = $value; + $this->mGeneralMessages['translatable'][$key] = $value; + } + } + } + + /** + * Get all the messages for a specific langauge (not English), without the + * fallback language messages, divided to groups: + * all - all the messages. + * required - messages which should be translated in order to get a complete translation. + * optional - messages which can be translated, the fallback translation is used if not translated. + * obsolete - messages which should not be translated, either because they are not exist, or they are ignored messages. + * translated - messages which are either required or optional, but translated from English and needed. + * + * @param $code The langauge code. + * + * @return The messages in this language. + */ + public function getMessages( $code ) { + $this->loadMessages( $code ); + return $this->mMessages[$code]; + } + + /** + * Get all the general English messages, divided to groups: + * all - all the messages. + * required - messages which should be translated to other languages in order to get a complete translation. + * optional - messages which can be translated to other languages, but it's not required for a complete translation. + * ignored - messages which should not be translated to other languages. + * translatable - messages which are either required or optional, but can be translated from English. + * + * @return The general English messages. + */ + public function getGeneralMessages() { + $this->loadGeneralMessages(); + return $this->mGeneralMessages; + } + + /** + * Get the untranslated messages for a specific language. + * + * @param $code The langauge code. + * + * @return The untranslated messages for this language. + */ + public function getUntranslatedMessages( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $requiredGeneralMessages = array_keys( $this->mGeneralMessages['required'] ); + $requiredMessages = array_keys( $this->mMessages[$code]['required'] ); + $untranslatedMessages = array(); + foreach ( array_diff( $requiredGeneralMessages, $requiredMessages ) as $key ) { + $untranslatedMessages[$key] = $this->mGeneralMessages['required'][$key]; + } + return $untranslatedMessages; + } + + /** + * Get the duplicate messages for a specific language. + * + * @param $code The langauge code. + * + * @return The duplicate messages for this language. + */ + public function getDuplicateMessages( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $duplicateMessages = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + if ( $this->mGeneralMessages['translatable'][$key] == $value ) { + $duplicateMessages[$key] = $value; + } + } + return $duplicateMessages; + } + + /** + * Get the messages which do not use some variables. + * + * @param $code The langauge code. + * + * @return The messages which do not use some variables in this language. + */ + public function getMessagesWithoutVariables( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' ); + $messagesWithoutVariables = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + $missing = false; + foreach ( $variables as $var ) { + if ( preg_match( "/$var/sU", $this->mGeneralMessages['translatable'][$key] ) && + !preg_match( "/$var/sU", $value ) ) { + $missing = true; + } + } + if ( $missing ) { + $messagesWithoutVariables[$key] = $value; + } + } + return $messagesWithoutVariables; + } + + /** + * Get the empty messages. + * + * @param $code The langauge code. + * + * @return The empty messages for this language. + */ + public function getEmptyMessages( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $emptyMessages = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + if ( $value === '' || $value === '-' ) { + $emptyMessages[$key] = $value; + } + } + return $emptyMessages; + } + + /** + * Get the messages with trailing whitespace. + * + * @param $code The langauge code. + * + * @return The messages with trailing whitespace in this language. + */ + public function getMessagesWithWhitespace( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $messagesWithWhitespace = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + if ( $this->mGeneralMessages['translatable'][$key] !== '' && $value !== rtrim( $value ) ) { + $messagesWithWhitespace[$key] = $value; + } + } + return $messagesWithWhitespace; + } + + /** + * Get the non-XHTML messages. + * + * @param $code The langauge code. + * + * @return The non-XHTML messages for this language. + */ + public function getNonXHTMLMessages( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $wrongPhrases = array( + '<hr *\\?>', + '<br *\\?>', + '<hr/>', + '<br/>', + ); + $wrongPhrases = '~(' . implode( '|', $wrongPhrases ) . ')~sDu'; + $nonXHTMLMessages = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + if ( preg_match( $wrongPhrases, $value ) ) { + $nonXHTMLMessages[$key] = $value; + } + } + return $nonXHTMLMessages; + } + + /** + * Get the messages which include wrong characters. + * + * @param $code The langauge code. + * + * @return The messages which include wrong characters in this language. + */ + public function getMessagesWithWrongChars( $code ) { + $this->loadGeneralMessages(); + $this->loadMessages( $code ); + $wrongChars = array( + '[LRM]' => "\xE2\x80\x8E", + '[RLM]' => "\xE2\x80\x8F", + '[LRE]' => "\xE2\x80\xAA", + '[RLE]' => "\xE2\x80\xAB", + '[POP]' => "\xE2\x80\xAC", + '[LRO]' => "\xE2\x80\xAD", + '[RLO]' => "\xE2\x80\xAB", + '[ZWSP]'=> "\xE2\x80\x8B", + '[NBSP]'=> "\xC2\xA0", + '[WJ]' => "\xE2\x81\xA0", + '[BOM]' => "\xEF\xBB\xBF", + '[FFFD]'=> "\xEF\xBF\xBD", + ); + $wrongRegExp = '/(' . implode( '|', array_values( $wrongChars ) ) . ')/sDu'; + $wrongCharsMessages = array(); + foreach ( $this->mMessages[$code]['translated'] as $key => $value ) { + if ( preg_match( $wrongRegExp, $value ) ) { + foreach ( $wrongChars as $viewableChar => $hiddenChar ) { + $value = str_replace( $hiddenChar, $viewableChar, $value ); + } + $wrongCharsMessages[$key] = $value; + } + } + return $wrongCharsMessages; + } + + /** + * Output a messages list + * + * @param $messages The messages list + * @param $code The language code + * @param $text The text to show before the list (optional) + * @param $level The display level (optional) + * @param $links Show links (optional) + * @param $wikilang The langauge of the wiki to display the list in, for the links (optional) + */ + public function outputMessagesList( $messages, $code, $text = '', $level = 2, $links = false, $wikilang = null ) { + if ( count( $messages ) == 0 ) { + return; + } + if ( $text ) { + echo "$text\n"; + } + if ( $level == 1 ) { + echo "[messages are hidden]\n"; + } else { + foreach ( $messages as $key => $value ) { + if ( $links ) { + $displayKey = ucfirst( $key ); + if ( !isset( $wikilang ) ) { + global $wgContLang; + $wikilang = $wgContLang->getCode(); + } + if ( $code == $wikilang ) { + $displayKey = "[[MediaWiki:$displayKey|$key]]"; + } else { + $displayKey = "[[MediaWiki:$displayKey/$code|$key]]"; + } + } else { + $displayKey = $key; + } + if ( $level == 2 ) { + echo "* $displayKey\n"; + } else { + echo "* $displayKey: '$value'\n"; + } + } + } + } +} + +?> diff --git a/maintenance/language/splitLanguageFiles.inc b/maintenance/language/splitLanguageFiles.inc new file mode 100644 index 00000000..c2500778 --- /dev/null +++ b/maintenance/language/splitLanguageFiles.inc @@ -0,0 +1,1168 @@ +<?php +/** + * This is an experimental list. It will later be used with a script to split + * the languages files in several parts then the message system will only load + * in memory the parts which are actually needed. + * + * Generated using: grep -r foobar * + * + * $commonMsg is the default array. Other arrays will only be loaded if needed. + */ +$installerMsg = array ( +'mainpagetext', +'mainpagedocfooter', +); + +$ActionMsg = array ( +'delete' => array( + 'delete', + 'deletethispage', + 'undelete_short1', + 'undelete_short', + 'undelete', + 'undeletepage', + 'undeletepagetext', + 'undeletearticle', + 'undeleterevisions', + 'undeletehistory', + 'undeleterevision', + 'undeletebtn', + 'undeletedarticle', + 'undeletedrevisions', + 'undeletedtext', + ), +'move' => array( + 'move', + 'movethispage', +), +'revert' => array( + +), +'protect' => array( + 'confirmprotect', + 'confirmprotecttext', + 'confirmunprotect', + 'confirmunprotecttext', + 'protect', + 'protectcomment', + 'protectmoveonly', + 'protectpage', + 'protectsub', + 'protectthispage', + 'unprotect', + 'unprotectthispage', + 'unprotectsub', + 'unprotectcomment', +), +); + +$CreditsMsg = array( +'anonymous', +'siteuser', +'lastmodifiedby', +'and', +'othercontribs', +'others', +'siteusers', +'creditspage', +'nocredits', +); + +// When showing differences +$DifferenceMsg = array( +'previousdiff', +'nextdiff', +); + +// used on page edition +$EditMsg = array( +'bold_sample', +'bold_tip', +'italic_sample', +'italic_tip', +'link_sample', +'link_tip', +'extlink_sample', +'extlink_tip', +'headline_sample', +'headline_tip', +'math_sample', +'math_tip', +'nowiki_sample', +'nowiki_tip', +'image_sample', +'image_tip', +'media_sample', +'media_tip', +'sig_tip', +'hr_tip', + +'accesskey-search', +'accesskey-minoredit', +'accesskey-save', +'accesskey-preview', +'accesskey-diff', +'accesskey-compareselectedversions', +'tooltip-search', +'tooltip-minoredit', +'tooltip-save', +'tooltip-preview', +'tooltip-diff', +'tooltip-compareselectedversions', +'tooltip-watch', + +'copyrightwarning', +'copyrightwarning2', +'editconflict', +'editing', +'editingcomment', +'editingold', +'editingsection', +'explainconflict', +'infobox', +'infobox_alert', +'longpagewarning', +'nonunicodebrowser', +'previewconflict', +'previewnote', +'protectedpagewarning', +'readonlywarning', +'spamprotectiontitle', +'spamprotectiontext', +'spamprotectionmatch', +'templatesused', +'yourdiff', +'yourtext', +); + +// Per namespace +$NamespaceCategory = array ( +'category_header', +'categoryarticlecount', +'categoryarticlecount1', +'listingcontinuesabbrev', +'subcategories', +'subcategorycount', +'subcategorycount1', +'usenewcategorypage', +); + +$NamespaceImage = array ( +'deletedrevision', +'edit-externally', +'edit-externally-help', +'showbigimage', +); + +$NamespaceSpecialMsg = array( +'nosuchspecialpage', +'nospecialpagetext', +); + + + +// per special pages +$SpecialAllMessages = array( +'allmessages', +'allmessagesname', +'allmessagesdefault', +'allmessagescurrent', +'allmessagestext', +'allmessagesnotsupportedUI', +'allmessagesnotsupportedDB', +); + + +$SpecialAllPages = array( +'articlenamespace', +'allpagesformtext1', +'allpagesformtext2', +'allarticles', +'allpagesprev', +'allpagesnext', +'allpagesnamespace', +'allpagessubmit', +); + + +$SpecialAskSQLMsg = array( +'asksql', +'asksqltext', +'sqlislogged', +'sqlquery', +'querybtn', +'selectonly', +'querysuccessful', +); + +$SpecialBlockip = array( +'blockip', +'blockiptext', +'range_block_disabled', +'ipb_expiry_invalid', +'ip_range_invalid', +'ipbexpiry', +'ipbsubmit', +); + +$SpecialContributions = array( +'contribsub', +'contributionsall', +'newbies', +'nocontribs', +'ucnote', +'uclinks', +'uctop', +); + +$SpecialExportMsg = array ( +'export', +'exporttext', +'exportcuronly', +); + +$SpecialImagelist = array( +'imagelistall', +); + +$SpecialImportMsg = array ( +'import', +'importtext', +'importfailed', +'importnotext', +'importsuccess', +'importhistoryconflict', +); + +$SpecialLockdbMsg = array( +'lockdb', +'unlockdb', +'lockdbtext', +'unlockdbtext', +'lockconfirm', +'unlockconfirm', +'lockbtn', +'unlockbtn', +'locknoconfirm', +'lockdbsuccesssub', +'unlockdbsuccesssub', +'lockdbsuccesstext', +'unlockdbsuccesstext', +); + +$SpecialLogMsg = array( +'specialloguserlabel', +'speciallogtitlelabel', +); + +$SpecialMaintenance = array( +'maintenance', +'maintnancepagetext', +'maintenancebacklink', +'disambiguations', +'disambiguationspage', +'disambiguationstext', +'doubleredirects', +'doubleredirectstext', +'brokenredirects', +'brokenredirectstext', +'selflinks', +'selflinkstext', +'mispeelings', +'mispeelingstext', +'mispeelingspage', +'missinglanguagelinks', +'missinglanguagelinksbutton', +'missinglanguagelinkstext', +); + +$SpecialMakeSysopMsg = array ( +'already_bureaucrat', +'already_sysop', +'makesysop', +'makesysoptitle', +'makesysoptext', +'makesysopname', +'makesysopsubmit', +'makesysopok', +'makesysopfail', +'rights', +'set_rights_fail', +'set_user_rights', +'user_rights_set', +); + +$SpecialMovepageMsg = array( +'newtitle', +'movearticle', +'movenologin', +'movenologintext', +'movepage', +'movepagebtn', +'movepagetalktext', +'movepagetext', +'movetalk', +'pagemovedsub', +'pagemovedtext', +'talkexists', +'talkpagemoved', +'talkpagenotmoved', + +); + +$SpecialPreferencesMsg = array( +'tog-underline', +'tog-highlightbroken', +'tog-justify', +'tog-hideminor', +'tog-usenewrc', +'tog-numberheadings', +'tog-showtoolbar', +'tog-editondblclick', +'tog-editsection', +'tog-editsectiononrightclick', +'tog-showtoc', +'tog-rememberpassword', +'tog-editwidth', +'tog-watchdefault', +'tog-minordefault', +'tog-previewontop', +'tog-previewonfirst', +'tog-nocache', +'tog-enotifwatchlistpages', +'tog-enotifusertalkpages', +'tog-enotifminoredits', +'tog-enotifrevealaddr', +'tog-shownumberswatching', +'tog-rcusemodstyle', +'tog-showupdated', +'tog-fancysig', +'tog-externaleditor', + +'imagemaxsize', +'prefs-help-email', +'prefs-help-email-enotif', +'prefs-help-realname', +'prefs-help-userdata', +'prefs-misc', +'prefs-personal', +'prefs-rc', +'resetprefs', +'saveprefs', +'oldpassword', +'newpassword', +'retypenew', +'textboxsize', +'rows', +'columns', +'searchresultshead', +'resultsperpage', +'contextlines', +'contextchars', +'stubthreshold', +'recentchangescount', +'savedprefs', +'timezonelegend', +'timezonetext', +'localtime', +'timezoneoffset', +'servertime', +'guesstimezone', +'emailflag', +'defaultns', +'default', +); + +$SpecialRecentchangesMsg = array( +'changes', +'recentchanges', +'recentchanges-url', +'recentchangestext', +'rcloaderr', +'rcnote', +'rcnotefrom', +'rclistfrom', +'showhideminor', +'rclinks', +'rchide', +'rcliu', +'diff', +'hist', +'hide', +'show', +'tableform', +'listform', +'nchanges', +'minoreditletter', +'newpageletter', +'sectionlink', +'number_of_watching_users_RCview', +'number_of_watching_users_pageview', +'recentchangesall', +); + +$SpecialRecentchangeslinkedMsg = array( +'rclsub', +); + +$SpecialSearchMsg = array( +'searchresults', +'searchresulttext', +'searchquery', +'badquery', +'badquerytext', +'matchtotals', +'nogomatch', +'titlematches', +'notitlematches', +'textmatches', +'notextmatches', +); + +$SpecialSitesettingsMsg = array( +'sitesettings', +'sitesettings-features', +'sitesettings-permissions', +'sitesettings-memcached', +'sitesettings-debugging', +'sitesettings-caching', +'sitesettings-wgShowIPinHeader', +'sitesettings-wgUseDatabaseMessages', +'sitesettings-wgUseCategoryMagic', +'sitesettings-wgUseCategoryBrowser', +'sitesettings-wgHitcounterUpdateFreq', +'sitesettings-wgAllowExternalImages', +'sitesettings-permissions-readonly', +'sitesettings-permissions-whitelist', +'sitesettings-permissions-banning', +'sitesettings-permissions-miser', +'sitesettings-wgReadOnly', +'sitesettings-wgReadOnlyFile', +'sitesettings-wgWhitelistEdit', +'sitesettings-wgWhitelistRead', +'sitesettings-wgWhitelistAccount-user', +'sitesettings-wgWhitelistAccount-sysop', +'sitesettings-wgWhitelistAccount-developer', +'sitesettings-wgSysopUserBans', +'sitesettings-wgSysopRangeBans', +'sitesettings-wgDefaultBlockExpiry', +'sitesettings-wgMiserMode', +'sitesettings-wgDisableQueryPages', +'sitesettings-wgUseWatchlistCache', +'sitesettings-wgWLCacheTimeout', +'sitesettings-cookies', +'sitesettings-performance', +'sitesettings-images', +); + +$SpecialStatisticsMsg = array( +'statistics', +'sitestats', +'userstats', +'sitestatstext', +'userstatstext', +); + +$SpecialUndelte = array( +'deletepage', +); + +$SpecialUploadMsg = array( +'affirmation', +'badfilename', +'badfiletype', +'emptyfile', +'fileexists', +'filedesc', +'filename', +'filesource', +'filestatus', +'fileuploaded', +'ignorewarning', +'illegalfilename', +'largefile', +'minlength', +'noaffirmation', +'reupload', +'reuploaddesc', +'savefile', +'successfulupload', +'upload', +'uploadbtn', +'uploadcorrupt', +'uploaddisabled', +'uploadfile', +'uploadedimage', +'uploaderror', +'uploadlink', +'uploadlog', +'uploadlogpage', +'uploadlogpagetext', +'uploadnologin', +'uploadnologintext', +'uploadtext', +'uploadwarning', +); + +$SpecialUserlevelsMsg = array( +'saveusergroups', +'userlevels-editusergroup', +'userlevels-groupsavailable', +'userlevels-groupshelp', +'userlevels-groupsmember', +); + +$SpecialUserloginMsg = array( +'acct_creation_throttle_hit', +'loginend', +'loginsuccesstitle', +'loginsuccess', +'nocookiesnew', +'nocookieslogin', +'noemail', +'noname', +'nosuchuser', +'mailmypassword', +'mailmypasswordauthent', +'passwordremindermailsubject', +'passwordremindermailbody', +'passwordsent', +'passwordsentforemailauthentication', +'userexists', +'wrongpassword', +); + +$SpecialValidateMsg = array( +'val_yes', +'val_no', +'val_revision', +'val_time', +'val_list_header', +'val_add', +'val_del', +'val_warning', +'val_rev_for', +'val_rev_stats_link', +'val_iamsure', +'val_clear_old', +'val_merge_old', +'val_form_note', +'val_noop', +'val_percent', +'val_percent_single', +'val_total', +'val_version', +'val_tab', +'val_this_is_current_version', +'val_version_of', +'val_table_header', +'val_stat_link_text', +'val_view_version', +'val_validate_version', +'val_user_validations', +'val_no_anon_validation', +'val_validate_article_namespace_only', +'val_validated', +'val_article_lists', +'val_page_validation_statistics', +); + +$SpecialVersionMsg = array( +'special_version_prefix', +'special_version_postfix' +); + +$SpecialWatchlistMsg = array( +'watchlistall1', +'watchlistall2', +'wlnote', +'wlshowlast', +'wlsaved', +'wlhideshowown', +'wlshow', +'wlhide', +); + +$SpecialWhatlinkshereMsg = array( +'linklistsub', +'nolinkshere', +'isredirect', +); + + +$commonMsg = array ( +'sunday', +'monday', +'tuesday', +'wednesday', +'thursday', +'friday', +'saturday', +'january', +'february', +'march', +'april', +'may_long', +'june', +'july', +'august', +'september', +'october', +'november', +'december', +'jan', +'feb', +'mar', +'apr', +'may', +'jun', +'jul', +'aug', +'sep', +'oct', +'nov', +'dec', +'categories', +'category', +'linktrail', +'mainpage', +'portal', +'portal-url', +'about', +'aboutsite', +'aboutpage', +'article', +'help', +'helppage', +'wikititlesuffix', +'bugreports', +'bugreportspage', +'sitesupport', +'sitesupport-url', +'faq', +'faqpage', +'edithelp', +'newwindow', +'edithelppage', +'cancel', +'qbfind', +'qbbrowse', +'qbedit', +'qbpageoptions', +'qbpageinfo', +'qbmyoptions', +'qbspecialpages', +'moredotdotdot', +'mypage', +'mytalk', +'anontalk', +'navigation', +'metadata', +'metadata_page', +'currentevents', +'currentevents-url', +'disclaimers', +'disclaimerpage', +'errorpagetitle', +'returnto', +'tagline', +'whatlinkshere', +'search', +'go', +'history', +'history_short', +'info_short', +'printableversion', +'edit', +'editthispage', +'newpage', +'talkpage', +'specialpage', +'personaltools', +'postcomment', +'addsection', +'articlepage', +'subjectpage', +'talk', +'toolbox', +'userpage', +'wikipediapage', +'imagepage', +'viewtalkpage', +'otherlanguages', +'redirectedfrom', +'lastmodified', +'viewcount', +'copyright', +'poweredby', +'printsubtitle', +'protectedpage', +'administrators', +'sysoptitle', +'sysoptext', +'developertitle', +'developertext', +'bureaucrattitle', +'bureaucrattext', +'nbytes', +'ok', +'sitetitle', +'pagetitle', +'sitesubtitle', +'retrievedfrom', +'newmessages', +'newmessageslink', +'editsection', +'toc', +'showtoc', +'hidetoc', +'thisisdeleted', +'restorelink', +'feedlinks', +'sitenotice', +'nstab-main', +'nstab-user', +'nstab-media', +'nstab-special', +'nstab-wp', +'nstab-image', +'nstab-mediawiki', +'nstab-template', +'nstab-help', +'nstab-category', +'nosuchaction', +'nosuchactiontext', + + +'error', +'databaseerror', +'dberrortext', +'dberrortextcl', +'noconnect', +'nodb', +'cachederror', +'laggedslavemode', +'readonly', +'enterlockreason', +'readonlytext', +'missingarticle', +'internalerror', +'filecopyerror', +'filerenameerror', +'filedeleteerror', +'filenotfound', +'unexpected', +'formerror', +'badarticleerror', +'cannotdelete', +'badtitle', +'badtitletext', +'perfdisabled', +'perfdisabledsub', +'perfcached', +'wrong_wfQuery_params', +'viewsource', +'protectedtext', +'seriousxhtmlerrors', +'logouttitle', +'logouttext', +'welcomecreation', + +'loginpagetitle', +'yourname', +'yourpassword', +'yourpasswordagain', +'newusersonly', +'remembermypassword', +'loginproblem', +'alreadyloggedin', +'login', +'loginprompt', +'userlogin', +'logout', +'userlogout', +'notloggedin', +'createaccount', +'createaccountmail', +'badretype', + +'youremail', +'yourrealname', +'yourlanguage', +'yourvariant', +'yournick', +'emailforlost', +'loginerror', +'nosuchusershort', + +'mailerror', +'emailauthenticated', +'emailnotauthenticated', +'invalidemailaddress', +'disableduntilauthent', +'disablednoemail', + +'summary', +'subject', +'minoredit', +'watchthis', +'savearticle', +'preview', +'showpreview', +'showdiff', +'blockedtitle', +'blockedtext', +'whitelistedittitle', +'whitelistedittext', +'whitelistreadtitle', +'whitelistreadtext', +'whitelistacctitle', +'whitelistacctext', +'loginreqtitle', +'loginreqtext', +'accmailtitle', +'accmailtext', +'newarticle', +'newarticletext', +'talkpagetext', +'anontalkpagetext', +'noarticletext', +'clearyourcache', +'usercssjsyoucanpreview', +'usercsspreview', +'userjspreview', +'updated', +'note', +'storedversion', // not used ? Editpage ? +'revhistory', +'nohistory', +'revnotfound', +'revnotfoundtext', +'loadhist', +'currentrev', +'revisionasof', +'revisionasofwithlink', +'previousrevision', +'nextrevision', +'currentrevisionlink', +'cur', +'next', +'last', +'orig', +'histlegend', +'history_copyright', +'difference', +'loadingrev', +'lineno', +'editcurrent', +'selectnewerversionfordiff', +'selectolderversionfordiff', +'compareselectedversions', + +'prevn', +'nextn', +'viewprevnext', +'showingresults', +'showingresultsnum', +'nonefound', +'powersearch', +'powersearchtext', +'searchdisabled', +'googlesearch', +'blanknamespace', +'preferences', +'prefsnologin', +'prefsnologintext', +'prefslogintext', +'prefsreset', +'qbsettings', +'qbsettingsnote', +'changepassword', +'skin', +'math', +'dateformat', + +'math_failure', +'math_unknown_error', +'math_unknown_function', +'math_lexing_error', +'math_syntax_error', +'math_image_error', +'math_bad_tmpdir', +'math_bad_output', +'math_notexvc', + + + + + + +'grouplevels-lookup-group', +'grouplevels-group-edit', +'editgroup', +'addgroup', +'userlevels-lookup-user', +'userlevels-user-editname', +'editusergroup', +'grouplevels-editgroup', +'grouplevels-addgroup', +'grouplevels-editgroup-name', +'grouplevels-editgroup-description', +'savegroup', + +// common to several pages +'copyrightpage', +'copyrightpagename', +'imagelist', +'imagelisttext', +'ilshowmatch', +'ilsubmit', +'showlast', +'byname', +'bydate', +'bysize', + + + +'imgdelete', +'imgdesc', +'imglegend', +'imghistory', +'revertimg', +'deleteimg', +'deleteimgcompletely', +'imghistlegend', +'imagelinks', +'linkstoimage', +'nolinkstoimage', + +// unused ?? +'uploadedfiles', +'getimagelist', + + +'sharedupload', +'shareduploadwiki', + +// Special pages names +'orphans', +'geo', +'validate', +'lonelypages', +'uncategorizedpages', +'uncategorizedcategories', +'unusedimages', +'popularpages', +'nviews', +'wantedpages', +'nlinks', +'allpages', +'randompage', +'randompage-url', +'shortpages', +'longpages', +'deadendpages', +'listusers', +'specialpages', +'spheading', +'restrictedpheading', +'recentchangeslinked', + + +'debug', +'newpages', +'ancientpages', +'intl', +'unusedimagestext', +'booksources', +'categoriespagetext', +'data', +'userlevels', +'grouplevels', +'booksourcetext', +'isbn', +'rfcurl', +'pubmedurl', +'alphaindexline', +'version', +'log', +'alllogstext', +'nextpage', +'mailnologin', +'mailnologintext', +'emailuser', +'emailpage', +'emailpagetext', +'usermailererror', +'defemailsubject', +'noemailtitle', +'noemailtext', +'emailfrom', +'emailto', +'emailsubject', +'emailmessage', +'emailsend', +'emailsent', +'emailsenttext', +'watchlist', +'watchlistsub', +'nowatchlist', +'watchnologin', +'watchnologintext', +'addedwatch', +'addedwatchtext', +'removedwatch', +'removedwatchtext', +'watch', +'watchthispage', +'unwatch', +'unwatchthispage', +'notanarticle', +'watchnochange', +'watchdetails', +'watchmethod-recent', +'watchmethod-list', +'removechecked', +'watchlistcontains', +'watcheditlist', +'removingchecked', +'couldntremove', +'iteminvalidname', + +'updatedmarker', +'email_notification_mailer', +'email_notification_infotext', +'email_notification_reset', +'email_notification_newpagetext', +'email_notification_to', +'email_notification_subject', +'email_notification_lastvisitedrevisiontext', +'email_notification_body', + +'confirm', +'excontent', +'exbeforeblank', +'exblank', +'confirmdelete', +'deletesub', +'historywarning', +'confirmdeletetext', +'actioncomplete', +'deletedtext', +'deletedarticle', +'dellogpage', +'dellogpagetext', +'deletionlog', +'reverted', +'deletecomment', +'imagereverted', +'rollback', +'rollback_short', +'rollbacklink', +'rollbackfailed', +'cantrollback', +'alreadyrolled', +'revertpage', +'editcomment', +'sessionfailure', + +'protectlogpage', +'protectlogtext', + +'protectedarticle', +'unprotectedarticle', + +'contributions', +'mycontris', +'notargettitle', // not used ? +'notargettext', // not used ? + +'linkshere', + +'ipaddress', +'ipadressorusername', // not used ? +'ipbreason', + +'badipaddress', +'noblockreason', +'blockipsuccesssub', +'blockipsuccesstext', +'unblockip', +'unblockiptext', +'ipusubmit', +'ipusuccess', +'ipblocklist', +'blocklistline', +'blocklink', +'unblocklink', +'contribslink', +'autoblocker', +'blocklogpage', +'blocklogentry', +'blocklogtext', +'unblocklogentry', // not used ? + +'proxyblocker', +'proxyblockreason', +'proxyblocksuccess', +'sorbs', +'sorbsreason', + +'setbureaucratflag', +'bureaucratlog', +'rightslogtext', +'bureaucratlogentry', + +'articleexists', // not used ? + +'movedto', +'1movedto2', +'1movedto2_redir', +'movelogpage', +'movelogpagetext', + +'thumbnail-more', +'missingimage', +'filemissing', +'Monobook.css', +'nodublincore', +'nocreativecommons', +'notacceptable', + +// used in Article:: +'infosubtitle', +'numedits', +'numtalkedits', +'numwatchers', +'numauthors', +'numtalkauthors', + +// not used ? +'mw_math_png', +'mw_math_simple', +'mw_math_html', +'mw_math_source', +'mw_math_modern', +'mw_math_mathml', + +// Patrolling +'markaspatrolleddiff', +'markaspatrolledlink', +'markaspatrolledtext', +'markedaspatrolled', +'markedaspatrolledtext', +'rcpatroldisabled', // not used ? +'rcpatroldisabledtext', // not used ? + +'Monobook.js', +'newimages', +'noimages', +'variantname-zh-cn', +'variantname-zh-tw', +'variantname-zh-hk', +'variantname-zh-sg', +'variantname-zh', +'zhconversiontable', +'passwordtooshort', // sp preferences / userlogin +); +?> diff --git a/maintenance/language/splitLanguageFiles.php b/maintenance/language/splitLanguageFiles.php new file mode 100644 index 00000000..2263e611 --- /dev/null +++ b/maintenance/language/splitLanguageFiles.php @@ -0,0 +1,13 @@ +<?php +/** + * splitLanguageFiles + * Should read each of the languages files then split them in several subpart + * under ./languages/XX/ according to the arrays in splitLanguageFiles.inc . + * + * Also need to rewrite the wfMsg system / message-cache. + */ + +include(dirname(__FILE__).'/../commandLine.inc'); + + +?> diff --git a/maintenance/language/transstat.php b/maintenance/language/transstat.php new file mode 100644 index 00000000..590da121 --- /dev/null +++ b/maintenance/language/transstat.php @@ -0,0 +1,211 @@ +<?php +/** + * Statistics about the localisation. + * + * @package MediaWiki + * @subpackage Maintenance + * + * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com> + * @author Ashar Voultoiz <thoane@altern.org> + * + * Output is posted from time to time on: + * http://meta.wikimedia.org/wiki/Localization_statistics + */ + +require_once( 'maintenance/commandLine.inc' ); +require_once( 'languages.inc' ); + +if ( isset( $options['help'] ) ) { + showUsage(); +} + +# Default output is WikiText +if ( !isset( $options['output'] ) ) { + $options['output'] = 'wiki'; +} + +/** Print a usage message*/ +function showUsage() { + print <<<END +Usage: php transstat.php [--help] [--output=csv|text|wiki] + --help : this helpful message + --output : select an output engine one of: + * 'csv' : Comma Separated Values. + * 'wiki' : MediaWiki syntax (default). + * 'metawiki' : MediaWiki syntax used for Meta-Wiki. + * 'text' : Text with tabs. +Example: php maintenance/transstat.php --output=text + +END; + exit(); +} + +/** A general output object. Need to be overriden */ +class statsOutput { + function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) { + return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total ); + } + + # Override the following methods + function heading() { + } + function footer() { + } + function blockstart() { + } + function blockend() { + } + function element( $in, $heading = false ) { + } +} + +/** Outputs WikiText */ +class wikiStatsOutput extends statsOutput { + function heading() { + global $IP; + $version = SpecialVersion::getVersion( $IP ); + echo "'''Statistics are based on:''' <code>" . $version . "</code>\n\n"; + echo "'''Note:''' These statistics can be generated by running <code>php maintenance/language/transstat.php</code>.\n\n"; + echo "For additional information on specific languages (the message names, the actual problems, etc.), run <code>php maintenance/language/checkLanguage.php --lang=foo</code>.\n\n"; + echo '{| border="2" cellpadding="4" cellspacing="0" style="background-color: #F9F9F9; border: 1px #AAAAAA solid; border-collapse: collapse;" width="100%"'."\n"; + } + function footer() { + echo "|}\n"; + } + function blockstart() { + echo "|-\n"; + } + function blockend() { + echo ''; + } + function element( $in, $heading = false ) { + echo ($heading ? '!' : '|') . " $in\n"; + } + function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) { + $v = @round(255 * $subset / $total); + if ( $revert ) { + $v = 255 - $v; + } + if ( $v < 128 ) { + # Red to Yellow + $red = 'FF'; + $green = sprintf( '%02X', 2 * $v ); + } else { + # Yellow to Green + $red = sprintf('%02X', 2 * ( 255 - $v ) ); + $green = 'FF'; + } + $blue = '00'; + $color = $red . $green . $blue; + + $percent = statsOutput::formatPercent( $subset, $total, $revert, $accuracy ); + return 'bgcolor="#'. $color .'" | '. $percent; + } +} + +/** Outputs WikiText and appends category and text only used for Meta-Wiki */ +class metawikiStatsOutput extends wikiStatsOutput { + function heading() { + echo "See [[MediaWiki localisation]] to learn how you can help translating MediaWiki.\n\n"; + parent::heading(); + } + function footer() { + parent::footer(); + echo "\n[[Category:Localisation|Statistics]]\n"; + } +} + +/** Output text. To be used on a terminal for example. */ +class textStatsOutput extends statsOutput { + function element( $in, $heading = false ) { + echo $in."\t"; + } + function blockend() { + echo "\n"; + } +} + +/** csv output. Some people love excel */ +class csvStatsOutput extends statsOutput { + function element( $in, $heading = false ) { + echo $in . ";"; + } + function blockend() { + echo "\n"; + } +} + +# Select an output engine +switch ( $options['output'] ) { + case 'wiki': + $wgOut = new wikiStatsOutput(); + break; + case 'metawiki': + $wgOut = new metawikiStatsOutput(); + break; + case 'text': + $wgOut = new textStatsOutput(); + break; + case 'csv': + $wgOut = new csvStatsOutput(); + break; + default: + showUsage(); +} + +# Languages +$wgLanguages = new languages(); + +# Header +$wgOut->heading(); +$wgOut->blockstart(); +$wgOut->element( 'Language', true ); +$wgOut->element( 'Translated', true ); +$wgOut->element( '%', true ); +$wgOut->element( 'Obsolete', true ); +$wgOut->element( '%', true ); +$wgOut->element( 'Problematic', true ); +$wgOut->element( '%', true ); +$wgOut->blockend(); + +$wgGeneralMessages = $wgLanguages->getGeneralMessages(); +$wgRequiredMessagesNumber = count( $wgGeneralMessages['required'] ); + +foreach ( $wgLanguages->getLanguages() as $code ) { + # Don't check English or RTL English + if ( $code == 'en' || $code == 'enRTL' ) { + continue; + } + + # Calculate the numbers + $language = $wgContLang->getLanguageName( $code ); + $messages = $wgLanguages->getMessages( $code ); + $messagesNumber = count( $messages['translated'] ); + $requiredMessagesNumber = count( $messages['required'] ); + $requiredMessagesPercent = $wgOut->formatPercent( $requiredMessagesNumber, $wgRequiredMessagesNumber ); + $obsoleteMessagesNumber = count( $messages['obsolete'] ); + $obsoleteMessagesPercent = $wgOut->formatPercent( $obsoleteMessagesNumber, $messagesNumber, true ); + $messagesWithoutVariables = $wgLanguages->getMessagesWithoutVariables( $code ); + $emptyMessages = $wgLanguages->getEmptyMessages( $code ); + $messagesWithWhitespace = $wgLanguages->getMessagesWithWhitespace( $code ); + $nonXHTMLMessages = $wgLanguages->getNonXHTMLMessages( $code ); + $messagesWithWrongChars = $wgLanguages->getMessagesWithWrongChars( $code ); + $problematicMessagesNumber = count( array_unique( array_merge( $messagesWithoutVariables, $emptyMessages, $messagesWithWhitespace, $nonXHTMLMessages, $messagesWithWrongChars ) ) ); + $problematicMessagesPercent = $wgOut->formatPercent( $problematicMessagesNumber, $messagesNumber, true ); + + # Output them + $wgOut->blockstart(); + $wgOut->element( "$language ($code)" ); + $wgOut->element( "$requiredMessagesNumber/$wgRequiredMessagesNumber" ); + $wgOut->element( $requiredMessagesPercent ); + $wgOut->element( "$obsoleteMessagesNumber/$messagesNumber" ); + $wgOut->element( $obsoleteMessagesPercent ); + $wgOut->element( "$problematicMessagesNumber/$messagesNumber" ); + $wgOut->element( $problematicMessagesPercent ); + $wgOut->blockend(); +} + +# Footer +$wgOut->footer(); + +?> diff --git a/maintenance/language/unusedMessages.php b/maintenance/language/unusedMessages.php new file mode 100644 index 00000000..8b117eca --- /dev/null +++ b/maintenance/language/unusedMessages.php @@ -0,0 +1,42 @@ +<?php +/** + * Prints out messages in localisation files that are no longer used. + * + * @package MediaWiki + * @subpackage Maintenance + */ + +require_once(dirname(__FILE__).'/../commandLine.inc'); + +if ( isset( $args[0] ) ) { + $code = $args[0]; +} else { + $code = $wgLang->getCode(); +} + +if ( $code == 'en' ) { + print "Current selected language is English. Cannot check translations.\n"; + exit(); +} + +$filename = Language::getMessagesFileName( $code ); +if ( file_exists( $filename ) ) { + require( $filename ); +} else { + $messages = array(); +} + +$count = $total = 0; +$wgEnglishMessages = Language::getMessagesFor( 'en' ); +$wgLocalMessages = $messages; + +foreach ( $wgLocalMessages as $key => $msg ) { + ++$total; + if ( !isset( $wgEnglishMessages[$key] ) ) { + print "* $key\n"; + ++$count; + } +} + +print "{$count} messages of {$total} are unused in the language {$code}\n"; +?> diff --git a/maintenance/language/validate.php b/maintenance/language/validate.php new file mode 100644 index 00000000..10d98d37 --- /dev/null +++ b/maintenance/language/validate.php @@ -0,0 +1,40 @@ +<?php + +if ( !isset( $argv[1] ) ) { + print "Usage: php {$argv[0]} <filename>\n"; + exit( 1 ); +} +array_shift( $argv ); + +define( 'MEDIAWIKI', 1 ); +define( 'NOT_REALLY_MEDIAWIKI', 1 ); + +$IP = dirname( __FILE__ ) . '/../..'; + +require_once( "$IP/includes/Defines.php" ); +require_once( "$IP/languages/Language.php" ); + +$files = array(); +foreach ( $argv as $arg ) { + $files = array_merge( $files, glob( $arg ) ); +} + +foreach ( $files as $filename ) { + print "$filename..."; + $vars = getVars( $filename ); + $keys = array_keys( $vars ); + $diff = array_diff( $keys, Language::$mLocalisationKeys ); + if ( $diff ) { + print "\nWarning: unrecognised variable(s): " . implode( ', ', $diff ) ."\n"; + } else { + print " ok\n"; + } +} + +function getVars( $filename ) { + require( $filename ); + $vars = get_defined_vars(); + unset( $vars['filename'] ); + return $vars; +} +?> |