var $mKeys, $mParserOptions, $mParser;
var $mExtensionMessages = array();
var $mInitialised = false;
- var $mAllMessagesLoaded; // Extension messages
+ var $mAllMessagesLoaded = array(); // Extension messages
// Variable for tracking which variables are loaded
var $mLoadedLanguages = array();
/**
* ParserOptions is lazy initialised.
- * Access should probably be protected.
*/
function getParserOptions() {
if ( !$this->mParserOptions ) {
global $wgLocalMessageCache;
$filename = "$wgLocalMessageCache/messages-" . wfWikiID() . "-$code";
- wfMkdirParents( $wgLocalMessageCache, 0777 ); // might fail
+ wfMkdirParents( $wgLocalMessageCache ); // might fail
wfSuppressWarnings();
$file = fopen( $filename, 'w' );
$filename = "$wgLocalMessageCache/messages-" . wfWikiID() . "-$code";
$tempFilename = $filename . '.tmp';
- wfMkdirParents( $wgLocalMessageCache, 0777 ); // might fail
+ wfMkdirParents( $wgLocalMessageCache ); // might fail
wfSuppressWarnings();
$file = fopen( $tempFilename, 'w');
$this->lock($cacheKey);
- $cache = $this->loadFromDB( $code );
- $success = $this->setCache( $cache, $code );
+ # Limit the concurrency of loadFromDB to a single process
+ # This prevents the site from going down when the cache expires
+ $statusKey = wfMemcKey( 'messages', $code, 'status' );
+ $success = $this->mMemc->add( $statusKey, 'loading', MSG_LOAD_TIMEOUT );
if ( $success ) {
- $this->saveToCaches( $cache, true, $code );
+ $cache = $this->loadFromDB( $code );
+ $success = $this->setCache( $cache, $code );
+ }
+ if ( $success ) {
+ $success = $this->saveToCaches( $cache, true, $code );
+ if ( $success ) {
+ $this->mMemc->delete( $statusKey );
+ } else {
+ $this->mMemc->set( $statusKey, 'error', 60*5 );
+ wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
+ }
}
-
$this->unlock($cacheKey);
}
$sidebarKey = wfMemcKey( 'sidebar', $code );
$parserMemc->delete( $sidebarKey );
+ wfRunHooks( "MessageCacheReplace", array( $title, $text ) );
+
wfProfileOut( __METHOD__ );
}
global $wgLocalMessageCache, $wgLocalMessageCacheSerialized;
$cacheKey = wfMemcKey( 'messages', $code );
- $statusKey = wfMemcKey( 'messages', $code, 'status' );
-
- $success = $this->mMemc->add( $statusKey, 'loading', MSG_LOAD_TIMEOUT );
- if ( !$success ) return true; # Other process should be updating them now
$i = 0;
if ( $memc ) {
}
if ( $i == 20 ) {
- $this->mMemc->set( $statusKey, 'error', 60*5 );
- wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" );
$success = false;
} else {
- $this->mMemc->delete( $statusKey );
$success = true;
}
wfProfileOut( __METHOD__ );
* functionality), or if it is a true boolean then
* use the wikis content language (also as a
* fallback).
- * @param bool $isFullKey Specifies whether $key is a two part key "lang/msg".
+ * @param bool $isFullKey Specifies whether $key is a two part key "msg/lang".
*/
function get( $key, $useDB = true, $langcode = true, $isFullKey = false ) {
- global $wgContLanguageCode, $wgContLang, $wgLang;
-
- # Identify which language to get or create a language object for.
- if( $langcode === $wgContLang->getCode() || $langcode === true ) {
- # $langcode is the language code of the wikis content language object.
- # or it is a boolean and value is true
- $lang =& $wgContLang;
- } elseif( $langcode === $wgLang->getCode() || $langcode === false ) {
- # $langcode is the language code of user language object.
- # or it was a boolean and value is false
- $lang =& $wgLang;
- } else {
- $validCodes = array_keys( Language::getLanguageNames() );
- if( in_array( $langcode, $validCodes ) ) {
- # $langcode corresponds to a valid language.
- $lang = Language::factory( $langcode );
- } else {
- # $langcode is a string, but not a valid language code; use content language.
- $lang =& $wgContLang;
- wfDebug( 'Invalid language code passed to MessageCache::get, falling back to content language.' );
- }
- }
+ global $wgContLanguageCode, $wgContLang;
+ $lang = wfGetLangObj( $langcode );
$langcode = $lang->getCode();
# If uninitialised, someone is trying to call this halfway through Setup.php
# Try the MediaWiki namespace
if( !$this->mDisable && $useDB ) {
$title = $wgContLang->ucfirst( $lckey );
- if(!$isFullKey && ($langcode != $wgContLanguageCode) ) {
+ if(!$isFullKey && ( $langcode != $wgContLanguageCode ) ) {
$title .= '/' . $langcode;
}
$message = $this->getMsgFromNamespace( $title, $langcode );
}
+ if( $message === false )
+ wfRunHooks( 'MessageNotInMwNs', array( &$message, $lckey, $langcode, $isFullKey ) );
# Try the extension array
if ( $message === false && isset( $this->mExtensionMessages[$langcode][$lckey] ) ) {
if( $message === false ) {
return '<' . htmlspecialchars($key) . '>';
}
+
+ # Fix whitespace
+ $message = strtr( $message,
+ array(
+ # Fix for trailing whitespace, removed by textarea
+ ' ' => ' ',
+ # Fix for NBSP, converted to space by firefox
+ ' ' => "\xc2\xa0",
+ ) );
+
return $message;
}
return $message;
}
- function transform( $message, $interface = false ) {
+ function transform( $message, $interface = false, $language = null ) {
// Avoid creating parser if nothing to transfrom
if( strpos( $message, '{{' ) === false ) {
return $message;
}
- global $wgParser;
+ global $wgParser, $wgParserConf;
if ( !$this->mParser && isset( $wgParser ) ) {
# Do some initialisation so that we don't have to do it twice
$wgParser->firstCallInit();
# Clone it and store it
- $this->mParser = clone $wgParser;
+ $class = $wgParserConf['class'];
+ if ( $class == 'Parser_DiffTest' ) {
+ # Uncloneable
+ $this->mParser = new $class( $wgParserConf );
+ } else {
+ $this->mParser = clone $wgParser;
+ }
#wfDebug( __METHOD__ . ": following contents triggered transform: $message\n" );
}
if ( $this->mParser ) {
$popts = $this->getParserOptions();
$popts->setInterfaceMessage( $interface );
+ $popts->setTargetLanguage( $language );
$message = $this->mParser->transformMsg( $message, $popts );
}
return $message;
* @param string $lang The messages language, English by default
*/
function addMessage( $key, $value, $lang = 'en' ) {
- $this->mExtensionMessages[$lang][$key] = $value;
+ global $wgContLang;
+ # Normalise title-case input
+ $lckey = str_replace( ' ', '_', $wgContLang->lcfirst( $key ) );
+ $this->mExtensionMessages[$lang][$lckey] = $value;
}
/**
}
}
- function loadAllMessages() {
+ function loadAllMessages( $lang = false ) {
global $wgExtensionMessagesFiles;
- if ( $this->mAllMessagesLoaded ) {
+ $key = $lang === false ? '*' : $lang;
+ if ( isset( $this->mAllMessagesLoaded[$key] ) ) {
return;
}
- $this->mAllMessagesLoaded = true;
+ $this->mAllMessagesLoaded[$key] = true;
# Some extensions will load their messages when you load their class file
wfLoadAllExtensions();
# Others will respond to this hook
- wfRunHooks( 'LoadAllMessages' );
+ wfRunHooks( 'LoadAllMessages', array( $this ) );
# Some register their messages in $wgExtensionMessagesFiles
foreach ( $wgExtensionMessagesFiles as $name => $file ) {
- wfLoadExtensionMessages( $name );
+ wfLoadExtensionMessages( $name, $lang );
}
# Still others will respond to neither, they are EVIL. We sometimes need to know!
}
*/
function loadMessagesFile( $filename, $langcode = false ) {
global $wgLang, $wgContLang;
+ wfProfileIn( __METHOD__ );
$messages = $magicWords = false;
require( $filename );
global $wgContLang;
$wgContLang->addMagicWordsByLang( $magicWords );
}
+ wfProfileOut( __METHOD__ );
}
/**
* @param string $langcode Language code to process.
*/
function processMessagesArray( $messages, $langcode ) {
+ wfProfileIn( __METHOD__ );
$fallbackCode = $langcode;
$mergedMessages = array();
do {
if ( !empty($mergedMessages) )
$this->addMessages( $mergedMessages, $langcode );
+ wfProfileOut( __METHOD__ );
}
public function figureMessage( $key ) {
global $wgContLanguageCode;
- $pieces = explode('/', $key, 2);
+ $pieces = explode( '/', $key );
+ if( count( $pieces ) < 2 )
+ return array( $key, $wgContLanguageCode );
- $key = $pieces[0];
+ $lang = array_pop( $pieces );
+ $validCodes = Language::getLanguageNames();
+ if( !array_key_exists( $lang, $validCodes ) )
+ return array( $key, $wgContLanguageCode );
- # Language the user is translating to
- $langCode = isset($pieces[1]) ? $pieces[1] : $wgContLanguageCode;
- return array( $key, $langCode );
+ $message = implode( '/', $pieces );
+ return array( $message, $lang );
}
}