case 'db':
$storeClass = 'LCStoreDB';
break;
- case 'accel':
- $storeClass = 'LCStoreAccel';
- break;
case 'detect':
$storeClass = $wgCacheDirectory ? 'LCStoreCDB' : 'LCStoreDB';
break;
$deps = $this->store->get( $code, 'deps' );
$keys = $this->store->get( $code, 'list' );
$preload = $this->store->get( $code, 'preload' );
- // Different keys may expire separately, at least in LCStoreAccel
+ // Different keys may expire separately for some stores
if ( $deps === null || $keys === null || $preload === null ) {
wfDebug( __METHOD__ . "($code): cache missing, need to make one\n" );
*
* @param string $code
* @param array $deps
+ * @return array
*/
protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
global $IP;
if ( $coreData['fallbackSequence'][$len - 1] !== 'en' ) {
$coreData['fallbackSequence'][] = 'en';
}
+ }
- # Load the fallback localisation item by item and merge it
- foreach ( $coreData['fallbackSequence'] as $fbCode ) {
- # Load the secondary localisation from the source file to
- # avoid infinite cycles on cyclic fallbacks
- $fbData = $this->readSourceFilesAndRegisterDeps( $fbCode, $deps );
- if ( $fbData === false ) {
- continue;
- }
+ $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] );
- foreach ( self::$allKeys as $key ) {
- if ( !isset( $fbData[$key] ) ) {
- continue;
- }
+ wfProfileIn( __METHOD__ . '-fallbacks' );
+
+ # Load non-JSON localisation data for extensions
+ $extensionData = array_combine(
+ $codeSequence,
+ array_fill( 0, count( $codeSequence ), $initialData ) );
+ foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
+ if ( isset( $wgMessagesDirs[$extension] ) ) {
+ # This extension has JSON message data; skip the PHP shim
+ continue;
+ }
- if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) {
- $this->mergeItem( $key, $coreData[$key], $fbData[$key] );
+ $data = $this->readPHPFile( $fileName, 'extension' );
+ $used = false;
+
+ foreach ( $data as $key => $item ) {
+ foreach ( $codeSequence as $csCode ) {
+ if ( isset( $item[$csCode] ) ) {
+ $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
+ $used = true;
}
}
}
- }
- $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] );
+ if ( $used ) {
+ $deps[] = new FileDependency( $fileName );
+ }
+ }
- # Load core messages and the extension localisations.
- wfProfileIn( __METHOD__ . '-extensions' );
+ # Load the localisation data for each fallback, then merge it into the full array
$allData = $initialData;
- foreach ( $wgMessagesDirs as $dirs ) {
- foreach ( (array)$dirs as $dir ) {
- foreach ( $codeSequence as $csCode ) {
+ foreach ( $codeSequence as $csCode ) {
+ $csData = $initialData;
+
+ # Load core messages and the extension localisations.
+ foreach ( $wgMessagesDirs as $dirs ) {
+ foreach ( (array)$dirs as $dir ) {
$fileName = "$dir/$csCode.json";
$data = $this->readJSONFile( $fileName );
foreach ( $data as $key => $item ) {
- $this->mergeItem( $key, $allData[$key], $item );
+ $this->mergeItem( $key, $csData[$key], $item );
}
$deps[] = new FileDependency( $fileName );
}
}
- }
- foreach ( $wgExtensionMessagesFiles as $extension => $fileName ) {
- if ( isset( $wgMessagesDirs[$extension] ) ) {
- # Already loaded the JSON files for this extension; skip the PHP shim
- continue;
+ # Merge non-JSON extension data
+ if ( isset( $extensionData[$csCode] ) ) {
+ foreach ( $extensionData[$csCode] as $key => $item ) {
+ $this->mergeItem( $key, $csData[$key], $item );
+ }
}
- $data = $this->readPHPFile( $fileName, 'extension' );
- $used = false;
-
- foreach ( $data as $key => $item ) {
- if ( $this->mergeExtensionItem( $codeSequence, $key, $allData[$key], $item ) ) {
- $used = true;
+ if ( $csCode === $code ) {
+ # Merge core data into extension data
+ foreach ( $coreData as $key => $item ) {
+ $this->mergeItem( $key, $csData[$key], $item );
+ }
+ } else {
+ # Load the secondary localisation from the source file to
+ # avoid infinite cycles on cyclic fallbacks
+ $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
+ if ( $fbData !== false ) {
+ # Only merge the keys that make sense to merge
+ foreach ( self::$allKeys as $key ) {
+ if ( !isset( $fbData[$key] ) ) {
+ continue;
+ }
+
+ if ( is_null( $coreData[$key] ) || $this->isMergeableKey( $key ) ) {
+ $this->mergeItem( $key, $csData[$key], $fbData[$key] );
+ }
+ }
}
}
- if ( $used ) {
- $deps[] = new FileDependency( $fileName );
+ # Allow extensions an opportunity to adjust the data for this
+ # fallback
+ wfRunHooks( 'LocalisationCacheRecacheFallback', array( $this, $csCode, &$csData ) );
+
+ # Merge the data for this fallback into the final array
+ if ( $csCode === $code ) {
+ $allData = $csData;
+ } else {
+ foreach ( self::$allKeys as $key ) {
+ if ( !isset( $csData[$key] ) ) {
+ continue;
+ }
+
+ if ( is_null( $allData[$key] ) || $this->isMergeableKey( $key ) ) {
+ $this->mergeItem( $key, $allData[$key], $csData[$key] );
+ }
+ }
}
}
- # Merge core data into extension data
- foreach ( $coreData as $key => $item ) {
- $this->mergeItem( $key, $allData[$key], $item );
- }
- wfProfileOut( __METHOD__ . '-extensions' );
+ wfProfileOut( __METHOD__ . '-fallbacks' );
# Add cache dependencies for any referenced globals
$deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
# HACK: If using a null (i.e. disabled) storage backend, we
# can't write to the MessageBlobStore either
if ( $purgeBlobs && !$this->store instanceof LCStoreNull ) {
- MessageBlobStore::clear();
+ MessageBlobStore::getInstance()->clear();
}
wfProfileOut( __METHOD__ );
function set( $key, $value );
}
-/**
- * LCStore implementation which uses PHP accelerator to store data.
- * This will work if one of XCache, WinCache or APC cacher is configured.
- * (See ObjectCache.php)
- */
-class LCStoreAccel implements LCStore {
- private $currentLang;
- private $keys;
-
- public function __construct() {
- $this->cache = wfGetCache( CACHE_ACCEL );
- }
-
- public function get( $code, $key ) {
- $k = wfMemcKey( 'l10n', $code, 'k', $key );
- $r = $this->cache->get( $k );
-
- return $r === false ? null : $r;
- }
-
- public function startWrite( $code ) {
- $k = wfMemcKey( 'l10n', $code, 'l' );
- $keys = $this->cache->get( $k );
- if ( $keys ) {
- foreach ( $keys as $k ) {
- $this->cache->delete( $k );
- }
- }
- $this->currentLang = $code;
- $this->keys = array();
- }
-
- public function finishWrite() {
- if ( $this->currentLang ) {
- $k = wfMemcKey( 'l10n', $this->currentLang, 'l' );
- $this->cache->set( $k, array_keys( $this->keys ) );
- }
- $this->currentLang = null;
- $this->keys = array();
- }
-
- public function set( $key, $value ) {
- if ( $this->currentLang ) {
- $k = wfMemcKey( 'l10n', $this->currentLang, 'k', $key );
- $this->keys[$k] = true;
- $this->cache->set( $k, $value );
- }
- }
-}
-
/**
* LCStore implementation which uses the standard DB functions to store data.
* This will work on any MediaWiki installation.