21use CLDRPluralRuleParser\Error as CLDRPluralRuleError;
22use CLDRPluralRuleParser\Evaluator;
28use Psr\Log\LoggerInterface;
57 private $manualRecache;
88 private $clearStoreCallbacks;
91 private $langNameUtils;
101 private $loadedItems = [];
107 private $loadedSubitems = [];
114 private $initialisedLangs = [];
121 private $shallowFallbacks = [];
126 private $recachedLangs = [];
132 'fallback',
'namespaceNames',
'bookstoreList',
133 'magicWords',
'messages',
'rtl',
134 'digitTransformTable',
'separatorTransformTable',
135 'minimumGroupingDigits',
'fallback8bitEncoding',
136 'linkPrefixExtension',
'linkTrail',
'linkPrefixCharset',
137 'namespaceAliases',
'dateFormats',
'datePreferences',
138 'datePreferenceMigrationMap',
'defaultDateFormat',
139 'specialPageAliases',
'imageFiles',
'preloadedMessages',
140 'namespaceGenderAliases',
'digitGroupingPattern',
'pluralRules',
141 'pluralRuleTypes',
'compiledPluralRules',
149 'namespaceAliases',
'dateFormats',
'imageFiles',
'preloadedMessages'
200 private $pluralRules =
null;
214 private $pluralRuleTypes =
null;
216 private $mergeableKeys =
null;
228 $storeArg[
'directory'] =
229 $conf[
'storeDirectory'] ?: $fallbackCacheDir;
231 if ( !empty( $conf[
'storeClass'] ) ) {
232 $storeClass = $conf[
'storeClass'];
233 } elseif ( $conf[
'store'] ===
'files' || $conf[
'store'] ===
'file' ||
234 ( $conf[
'store'] ===
'detect' && $storeArg[
'directory'] )
236 $storeClass = LCStoreCDB::class;
237 } elseif ( $conf[
'store'] ===
'db' || $conf[
'store'] ===
'detect' ) {
238 $storeClass = LCStoreDB::class;
239 $storeArg[
'server'] = $conf[
'storeServer'] ?? [];
240 } elseif ( $conf[
'store'] ===
'array' ) {
241 $storeClass = LCStoreStaticArray::class;
244 'Please set $wgLocalisationCacheConf[\'store\'] to something sensible.'
248 return new $storeClass( $storeArg );
254 public const CONSTRUCTOR_OPTIONS = [
258 MainConfigNames::ExtensionMessagesFiles,
259 MainConfigNames::MessagesDirs,
281 LoggerInterface $logger,
282 array $clearStoreCallbacks,
288 $this->options = $options;
289 $this->store = $store;
290 $this->logger = $logger;
291 $this->clearStoreCallbacks = $clearStoreCallbacks;
292 $this->langNameUtils = $langNameUtils;
293 $this->hookRunner =
new HookRunner( $hookContainer );
296 $this->manualRecache = $options->
get(
'manualRecache' );
306 if ( $this->mergeableKeys ===
null ) {
307 $this->mergeableKeys = array_fill_keys( array_merge(
308 self::$mergeableMapKeys,
309 self::$mergeableListKeys,
310 self::$mergeableAliasListKeys,
311 self::$optionalMergeKeys,
316 return isset( $this->mergeableKeys[$key] );
329 if ( !isset( $this->loadedItems[$code][$key] ) ) {
330 $this->loadItem( $code, $key );
333 if ( $key ===
'fallback' && isset( $this->shallowFallbacks[$code] ) ) {
334 return $this->shallowFallbacks[$code];
338 return $this->data[$code][$key];
349 if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
350 !isset( $this->loadedItems[$code][$key] )
352 $this->loadSubitem( $code, $key, $subkey );
355 return $this->data[$code][$key][$subkey] ??
null;
368 $subitem = $this->getSubitem( $code, $key, $subkey );
370 if ( $subitem ===
null ) {
375 return [ $subitem, $this->sourceLanguage[$code][$key][$subkey] ?? $code ];
391 if ( in_array( $key, self::$splitKeys ) ) {
392 return $this->getSubitem( $code,
'list', $key );
394 $item = $this->getItem( $code, $key );
395 if ( is_array( $item ) ) {
396 return array_keys( $item );
409 if ( !isset( $this->initialisedLangs[$code] ) ) {
410 $this->initLanguage( $code );
414 if ( isset( $this->loadedItems[$code][$key] ) ) {
418 if ( isset( $this->shallowFallbacks[$code] ) ) {
419 $this->loadItem( $this->shallowFallbacks[$code], $key );
424 if ( in_array( $key, self::$splitKeys ) ) {
425 $subkeyList = $this->getSubitem( $code,
'list', $key );
426 foreach ( $subkeyList as $subkey ) {
427 if ( isset( $this->data[$code][$key][$subkey] ) ) {
430 $this->loadSubitem( $code, $key, $subkey );
433 $this->data[$code][$key] = $this->store->get( $code, $key );
436 $this->loadedItems[$code][$key] =
true;
446 if ( !in_array( $key, self::$splitKeys ) ) {
447 $this->loadItem( $code, $key );
452 if ( !isset( $this->initialisedLangs[$code] ) ) {
453 $this->initLanguage( $code );
457 if ( isset( $this->loadedItems[$code][$key] ) ||
458 isset( $this->loadedSubitems[$code][$key][$subkey] )
463 if ( isset( $this->shallowFallbacks[$code] ) ) {
464 $this->loadSubitem( $this->shallowFallbacks[$code], $key, $subkey );
469 $value = $this->store->get( $code,
"$key:$subkey" );
470 if ( $value !==
null && in_array( $key, self::$sourcePrefixKeys ) ) {
472 $this->sourceLanguage[$code][$key][$subkey],
473 $this->data[$code][$key][$subkey]
474 ] = explode( self::SOURCEPREFIX_SEPARATOR, $value, 2 );
476 $this->data[$code][$key][$subkey] = $value;
479 $this->loadedSubitems[$code][$key][$subkey] =
true;
490 if ( $this->options->get(
'forceRecache' ) && !isset( $this->recachedLangs[$code] ) ) {
491 $this->logger->debug( __METHOD__ .
"($code): forced reload" );
496 $deps = $this->store->get( $code,
'deps' );
497 $keys = $this->store->get( $code,
'list' );
498 $preload = $this->store->get( $code,
'preload' );
500 if ( $deps ===
null ||
$keys ===
null || $preload ===
null ) {
501 $this->logger->debug( __METHOD__ .
"($code): cache missing, need to make one" );
506 foreach ( $deps as $dep ) {
512 $this->logger->debug( __METHOD__ .
"($code): cache for $code expired due to " .
528 if ( isset( $this->initialisedLangs[$code] ) ) {
532 $this->initialisedLangs[$code] =
true;
534 # If the code is of the wrong form for a Messages*.php file, do a shallow fallback
535 if ( !$this->langNameUtils->isValidBuiltInCode( $code ) ) {
536 $this->initShallowFallback( $code,
'en' );
541 # Recache the data if necessary
542 if ( !$this->manualRecache && $this->isExpired( $code ) ) {
543 if ( $this->langNameUtils->isSupportedLanguage( $code ) ) {
544 $this->recache( $code );
545 } elseif ( $code ===
'en' ) {
546 throw new MWException(
'MessagesEn.php is missing.' );
548 $this->initShallowFallback( $code,
'en' );
555 $preload = $this->getItem( $code,
'preload' );
556 if ( $preload ===
null ) {
557 if ( $this->manualRecache ) {
559 if ( $code ===
'en' ) {
560 throw new MWException(
'No localisation cache found for English. ' .
561 'Please run maintenance/rebuildLocalisationCache.php.' );
563 $this->initShallowFallback( $code,
'en' );
567 throw new MWException(
'Invalid or missing localisation cache.' );
571 foreach ( self::$sourcePrefixKeys as $key ) {
572 if ( !isset( $preload[$key] ) ) {
575 foreach ( $preload[$key] as $subkey => $value ) {
576 if ( $value !==
null ) {
578 $this->sourceLanguage[$code][$key][$subkey],
579 $preload[$key][$subkey]
580 ] = explode( self::SOURCEPREFIX_SEPARATOR, $value, 2 );
582 $preload[$key][$subkey] =
null;
587 $this->data[$code] = $preload;
588 foreach ( $preload as $key => $item ) {
589 if ( in_array( $key, self::$splitKeys ) ) {
590 foreach ( $item as $subkey => $subitem ) {
591 $this->loadedSubitems[$code][$key][$subkey] =
true;
594 $this->loadedItems[$code][$key] =
true;
606 $this->data[$primaryCode] =& $this->data[$fallbackCode];
607 $this->loadedItems[$primaryCode] =& $this->loadedItems[$fallbackCode];
608 $this->loadedSubitems[$primaryCode] =& $this->loadedSubitems[$fallbackCode];
609 $this->shallowFallbacks[$primaryCode] = $fallbackCode;
623 if ( $_fileType ==
'core' || $_fileType ==
'extension' ) {
624 foreach ( self::$allKeys as $key ) {
627 if ( isset( $$key ) ) {
631 } elseif ( $_fileType ==
'aliases' ) {
633 if ( isset( $aliases ) ) {
634 $data[
'aliases'] = $aliases;
637 throw new MWException( __METHOD__ .
": Invalid file type: $_fileType" );
650 if ( !is_readable( $fileName ) ) {
654 $json = file_get_contents( $fileName );
655 if ( $json ===
false ) {
659 $data = FormatJson::decode( $json,
true );
660 if ( $data ===
null ) {
661 throw new MWException( __METHOD__ .
": Invalid JSON file: $fileName" );
665 foreach ( $data as $key => $unused ) {
666 if ( $key ===
'' || $key[0] ===
'@' ) {
667 unset( $data[$key] );
681 $rules = $this->getPluralRules( $code );
682 if ( $rules ===
null ) {
686 $compiledRules = Evaluator::compile( $rules );
687 }
catch ( CLDRPluralRuleError $e ) {
688 $this->logger->debug( $e->getMessage() );
693 return $compiledRules;
704 if ( $this->pluralRules ===
null ) {
705 $this->loadPluralFiles();
707 return $this->pluralRules[$code] ??
null;
718 if ( $this->pluralRuleTypes ===
null ) {
719 $this->loadPluralFiles();
721 return $this->pluralRuleTypes[$code] ??
null;
728 foreach ( $this->getPluralFiles() as $fileName ) {
729 $this->loadPluralFile( $fileName );
733 private function getPluralFiles(): array {
737 "$IP/languages/data/plurals.xml",
739 "$IP/languages/data/plurals-mediawiki.xml",
752 $xml = file_get_contents( $fileName );
754 throw new MWException(
"Unable to read plurals file $fileName" );
756 $doc =
new DOMDocument;
757 $doc->loadXML( $xml );
758 $rulesets = $doc->getElementsByTagName(
"pluralRules" );
759 foreach ( $rulesets as $ruleset ) {
760 $codes = $ruleset->getAttribute(
'locales' );
763 $ruleElements = $ruleset->getElementsByTagName(
"pluralRule" );
764 foreach ( $ruleElements as $elt ) {
765 $ruleType = $elt->getAttribute(
'count' );
766 if ( $ruleType ===
'other' ) {
770 $rules[] = $elt->nodeValue;
771 $ruleTypes[] = $ruleType;
773 foreach ( explode(
' ', $codes ) as $code ) {
774 $this->pluralRules[$code] = $rules;
775 $this->pluralRuleTypes[$code] = $ruleTypes;
791 $fileName = $this->langNameUtils->getMessagesFileName( $code );
792 if ( !is_file( $fileName ) ) {
796 $data = $this->readPHPFile( $fileName,
'core' );
800 $data[
'pluralRules'] = $this->getPluralRules( $code );
802 $data[
'compiledPluralRules'] = $this->getCompiledPluralRules( $code );
804 $data[
'pluralRuleTypes'] = $this->getPluralRuleTypes( $code );
806 foreach ( $this->getPluralFiles() as $fileName ) {
820 protected function mergeItem( $key, &$value, $fallbackValue ) {
821 if ( $value !==
null ) {
822 if ( $fallbackValue !==
null ) {
823 if ( in_array( $key, self::$mergeableMapKeys ) ) {
824 $value += $fallbackValue;
825 } elseif ( in_array( $key, self::$mergeableListKeys ) ) {
826 $value = array_unique( array_merge( $fallbackValue, $value ) );
827 } elseif ( in_array( $key, self::$mergeableAliasListKeys ) ) {
828 $value = array_merge_recursive( $value, $fallbackValue );
829 } elseif ( in_array( $key, self::$optionalMergeKeys ) ) {
830 if ( !empty( $value[
'inherit'] ) ) {
831 $value = array_merge( $fallbackValue, $value );
834 unset( $value[
'inherit'] );
835 } elseif ( in_array( $key, self::$magicWordKeys ) ) {
836 $this->mergeMagicWords( $value, $fallbackValue );
840 $value = $fallbackValue;
849 foreach ( $fallbackValue as $magicName => $fallbackInfo ) {
850 if ( !isset( $value[$magicName] ) ) {
851 $value[$magicName] = $fallbackInfo;
853 $oldSynonyms = array_slice( $fallbackInfo, 1 );
854 $newSynonyms = array_slice( $value[$magicName], 1 );
855 $synonyms = array_values( array_unique( array_merge(
856 $newSynonyms, $oldSynonyms ) ) );
857 $value[$magicName] = array_merge( [ $fallbackInfo[0] ], $synonyms );
877 foreach ( $codeSequence as $code ) {
878 if ( isset( $fallbackValue[$code] ) ) {
879 $this->mergeItem( $key, $value, $fallbackValue[$code] );
898 'core' =>
"$IP/languages/i18n",
899 'exif' =>
"$IP/languages/i18n/exif",
900 'api' =>
"$IP/includes/api/i18n",
901 'rest' =>
"$IP/includes/Rest/i18n",
902 'oojs-ui' =>
"$IP/resources/lib/ooui/i18n",
903 'paramvalidator' =>
"$IP/includes/libs/ParamValidator/i18n",
904 ] + $this->options->get( MainConfigNames::MessagesDirs );
915 throw new MWException(
"Invalid language code requested" );
917 $this->recachedLangs[ $code ] =
true;
920 $initialData = array_fill_keys( self::$allKeys,
null );
921 $coreData = $initialData;
924 # Load the primary localisation from the source file
925 $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
926 $this->logger->debug( __METHOD__ .
": got localisation for $code from source" );
928 # Merge primary localisation
929 foreach ( $data as $key => $value ) {
930 $this->mergeItem( $key, $coreData[ $key ], $value );
933 # Fill in the fallback if it's not there already
935 if ( ( $coreData[
'fallback'] ===
null || $coreData[
'fallback'] ===
false ) && $code ===
'en' ) {
936 $coreData[
'fallback'] =
false;
937 $coreData[
'originalFallbackSequence'] = $coreData[
'fallbackSequence'] = [];
939 if ( $coreData[
'fallback'] !==
null ) {
940 $coreData[
'fallbackSequence'] = array_map(
'trim', explode(
',', $coreData[
'fallback'] ) );
942 $coreData[
'fallbackSequence'] = [];
944 $len = count( $coreData[
'fallbackSequence'] );
946 # Before we add the 'en' fallback for messages, keep a copy of
947 # the original fallback sequence
948 $coreData[
'originalFallbackSequence'] = $coreData[
'fallbackSequence'];
950 # Ensure that the sequence ends at 'en' for messages
951 if ( !$len || $coreData[
'fallbackSequence'][$len - 1] !==
'en' ) {
952 $coreData[
'fallbackSequence'][] =
'en';
956 $codeSequence = array_merge( [ $code ], $coreData[
'fallbackSequence'] );
957 $messageDirs = $this->getMessagesDirs();
959 # Load non-JSON localisation data for extensions
960 $extensionData = array_fill_keys( $codeSequence, $initialData );
961 foreach ( $this->options->get( MainConfigNames::ExtensionMessagesFiles ) as $extension => $fileName ) {
962 if ( isset( $messageDirs[$extension] ) ) {
963 # This extension has JSON message data; skip the PHP shim
967 $data = $this->readPHPFile( $fileName,
'extension' );
970 foreach ( $data as $key => $item ) {
971 foreach ( $codeSequence as $csCode ) {
972 if ( isset( $item[$csCode] ) ) {
975 if ( in_array( $key, self::$sourcePrefixKeys ) ) {
976 foreach ( $item[$csCode] as $subkey => $_ ) {
977 $this->sourceLanguage[$code][$key][$subkey] ??= $csCode;
980 $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
991 # Load the localisation data for each fallback, then merge it into the full array
992 $allData = $initialData;
993 foreach ( $codeSequence as $csCode ) {
994 $csData = $initialData;
996 # Load core messages and the extension localisations.
997 foreach ( $messageDirs as $dirs ) {
998 foreach ( (array)$dirs as $dir ) {
999 $fileName =
"$dir/$csCode.json";
1000 $messages = $this->readJSONFile( $fileName );
1002 foreach ( $messages as $subkey => $_ ) {
1003 $this->sourceLanguage[$code][
'messages'][$subkey] ??= $csCode;
1005 $this->mergeItem(
'messages', $csData[
'messages'], $messages );
1011 # Merge non-JSON extension data
1012 if ( isset( $extensionData[$csCode] ) ) {
1013 foreach ( $extensionData[$csCode] as $key => $item ) {
1014 $this->mergeItem( $key, $csData[$key], $item );
1018 if ( $csCode === $code ) {
1019 # Merge core data into extension data
1020 foreach ( $coreData as $key => $item ) {
1021 $this->mergeItem( $key, $csData[$key], $item );
1024 # Load the secondary localisation from the source file to
1025 # avoid infinite cycles on cyclic fallbacks
1026 $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
1027 # Only merge the keys that make sense to merge
1028 foreach ( self::$allKeys as $key ) {
1029 if ( !isset( $fbData[ $key ] ) ) {
1033 if ( ( $coreData[ $key ] ) ===
null || $this->isMergeableKey( $key ) ) {
1034 $this->mergeItem( $key, $csData[ $key ], $fbData[ $key ] );
1039 # Allow extensions an opportunity to adjust the data for this
1041 $this->hookRunner->onLocalisationCacheRecacheFallback( $this, $csCode, $csData );
1043 # Merge the data for this fallback into the final array
1044 if ( $csCode === $code ) {
1047 foreach ( self::$allKeys as $key ) {
1048 if ( !isset( $csData[$key] ) ) {
1053 if ( $allData[$key] ===
null || $this->isMergeableKey( $key ) ) {
1054 $this->mergeItem( $key, $allData[$key], $csData[$key] );
1060 if ( !isset( $allData[
'rtl'] ) ) {
1061 throw new MWException( __METHOD__ .
': Localisation data failed validation check! ' .
1062 'Check that your languages/messages/MessagesEn.php file is intact.' );
1065 # Add cache dependencies for any referenced globals
1066 $deps[
'wgExtensionMessagesFiles'] =
new GlobalDependency(
'wgExtensionMessagesFiles' );
1072 # Add dependencies to the cache entry
1073 $allData[
'deps'] = $deps;
1075 # Replace spaces with underscores in namespace names
1076 $allData[
'namespaceNames'] = str_replace(
' ',
'_', $allData[
'namespaceNames'] );
1078 # And do the same for special page aliases. $page is an array.
1079 foreach ( $allData[
'specialPageAliases'] as &$page ) {
1080 $page = str_replace(
' ',
'_', $page );
1082 # Decouple the reference to prevent accidental damage
1085 # If there were no plural rules, return an empty array
1086 if ( $allData[
'pluralRules'] ===
null ) {
1087 $allData[
'pluralRules'] = [];
1089 if ( $allData[
'compiledPluralRules'] ===
null ) {
1090 $allData[
'compiledPluralRules'] = [];
1092 # If there were no plural rule types, return an empty array
1093 if ( $allData[
'pluralRuleTypes'] ===
null ) {
1094 $allData[
'pluralRuleTypes'] = [];
1098 $allData[
'list'] = [];
1099 foreach ( self::$splitKeys as $key ) {
1100 $allData[
'list'][$key] = array_keys( $allData[$key] );
1104 $this->hookRunner->onLocalisationCacheRecache( $this, $code, $allData, $unused );
1106 # Save to the process cache and register the items loaded
1107 $this->data[$code] = $allData;
1108 foreach ( $allData as $key => $item ) {
1109 $this->loadedItems[$code][$key] =
true;
1112 # Prefix each item with its source language code before save
1113 foreach ( self::$sourcePrefixKeys as $key ) {
1115 foreach ( $allData[$key] as $subKey => $value ) {
1117 $allData[$key][$subKey] = ( $this->sourceLanguage[$code][$key][$subKey] ?? $code ) .
1118 self::SOURCEPREFIX_SEPARATOR . $value;
1122 # Set the preload key
1123 $allData[
'preload'] = $this->buildPreload( $allData );
1125 # Save to the persistent cache
1126 $this->store->startWrite( $code );
1127 foreach ( $allData as $key => $value ) {
1128 if ( in_array( $key, self::$splitKeys ) ) {
1129 foreach ( $value as $subkey => $subvalue ) {
1130 $this->store->set(
"$key:$subkey", $subvalue );
1133 $this->store->set( $key, $value );
1136 $this->store->finishWrite();
1138 # Clear out the MessageBlobStore
1139 # HACK: If using a null (i.e. disabled) storage backend, we
1140 # can't write to the MessageBlobStore either
1142 foreach ( $this->clearStoreCallbacks as $callback ) {
1157 $preload = [
'messages' => [] ];
1158 foreach ( self::$preloadedKeys as $key ) {
1159 $preload[$key] = $data[$key];
1162 foreach ( $data[
'preloadedMessages'] as $subkey ) {
1163 $subitem = $data[
'messages'][$subkey] ??
null;
1164 $preload[
'messages'][$subkey] = $subitem;
1176 unset( $this->data[$code] );
1177 unset( $this->loadedItems[$code] );
1178 unset( $this->loadedSubitems[$code] );
1179 unset( $this->initialisedLangs[$code] );
1180 unset( $this->shallowFallbacks[$code] );
1181 unset( $this->sourceLanguage[$code] );
1183 foreach ( $this->shallowFallbacks as $shallowCode => $fbCode ) {
1184 if ( $fbCode === $code ) {
1185 $this->unload( $shallowCode );
1194 foreach ( $this->initialisedLangs as
$lang => $unused ) {
1195 $this->unload(
$lang );
1204 $this->manualRecache =
false;
if(!defined( 'MEDIAWIKI')) if(ini_get('mbstring.func_overload')) if(!defined( 'MW_ENTRY_POINT')) global $IP
Environment checks.
Base class to represent dependencies for LocalisationCache entries.
isExpired()
Returns true if the dependency is expired, false otherwise.
Depend on a PHP constant.
Depend on a PHP global variable.
Null store backend, used to avoid DB errors during install.
Caching for the contents of localisation files.
static $magicWordKeys
Keys for items that are formatted like $magicWords.
buildPreload( $data)
Build the preload item from the given pre-cache data.
getSubitemWithSource( $code, $key, $subkey)
Get a subitem with its source language.
initLanguage( $code)
Initialise a language in this object.
static $mergeableMapKeys
Keys for items which consist of associative arrays, which may be merged by a fallback sequence.
readSourceFilesAndRegisterDeps( $code, &$deps)
Read the data from the source files for a given language, and register the relevant dependencies in t...
static $sourcePrefixKeys
Keys for items that will be prefixed with its source language code, which should be stripped out when...
isMergeableKey( $key)
Returns true if the given key is mergeable, that is, if it is an associative array which can be merge...
loadPluralFile( $fileName)
Load a plural XML file with the given filename, compile the relevant rules, and save the compiled rul...
getPluralRules( $code)
Get the plural rules for a given language from the XML files.
const SOURCEPREFIX_SEPARATOR
Separator for the source language prefix.
readPHPFile( $_fileName, $_fileType)
Read a PHP file containing localisation data.
readJSONFile( $fileName)
Read a JSON file containing localisation messages.
loadPluralFiles()
Load the plural XML files.
unload( $code)
Unload the data for a given language from the object cache.
unloadAll()
Unload all data.
disableBackend()
Disable the storage backend.
static $mergeableAliasListKeys
Keys for items which contain an array of arrays of equivalent aliases for each subitem.
getSubitemList( $code, $key)
Get the list of subitem keys for a given item.
__construct(ServiceOptions $options, LCStore $store, LoggerInterface $logger, array $clearStoreCallbacks, LanguageNameUtils $langNameUtils, HookContainer $hookContainer)
For constructor parameters, see the documentation for the LocalisationCacheConf setting in docs/Confi...
static $mergeableListKeys
Keys for items which are a numbered array.
recache( $code)
Load localisation data for a given language for both core and extensions and save it to the persisten...
isExpired( $code)
Returns true if the cache identified by $code is missing or expired.
mergeItem( $key, &$value, $fallbackValue)
Merge two localisation values, a primary and a fallback, overwriting the primary value in place.
$sourceLanguage
The source language of cached data items.
getSubitem( $code, $key, $subkey)
Get a subitem, for instance a single message for a given language.
mergeMagicWords(&$value, $fallbackValue)
initShallowFallback( $primaryCode, $fallbackCode)
Create a fallback from one language to another, without creating a complete persistent cache.
static getStoreFromConf(array $conf, $fallbackCacheDir)
Return a suitable LCStore as specified by the given configuration.
static $allKeys
All item keys.
getCompiledPluralRules( $code)
Get the compiled plural rules for a given language from the XML files.
static $optionalMergeKeys
Keys for items which contain an associative array, and may be merged if the primary value contains th...
getMessagesDirs()
Gets the combined list of messages dirs from core and extensions.
static $preloadedKeys
Keys which are loaded automatically by initLanguage()
getItem( $code, $key)
Get a cache item.
static $splitKeys
Keys for items where the subitems are stored in the backend separately.
loadItem( $code, $key)
Load an item into the cache.
getPluralRuleTypes( $code)
Get the plural rule types for a given language from the XML files.
loadSubitem( $code, $key, $subkey)
Load a subitem into the cache.
mergeExtensionItem( $codeSequence, $key, &$value, $fallbackValue)
Given an array mapping language code to localisation value, such as is found in extension *....
Depend on a MW configuration variable.
A class containing constants representing the names of configuration variables.
Interface for the persistence layer of LocalisationCache.
if(!isset( $args[0])) $lang