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,
278 LoggerInterface $logger,
279 array $clearStoreCallbacks,
285 $this->options = $options;
286 $this->store = $store;
287 $this->logger = $logger;
288 $this->clearStoreCallbacks = $clearStoreCallbacks;
289 $this->langNameUtils = $langNameUtils;
290 $this->hookRunner =
new HookRunner( $hookContainer );
293 $this->manualRecache = $options->
get(
'manualRecache' );
303 if ( $this->mergeableKeys ===
null ) {
304 $this->mergeableKeys = array_fill_keys( array_merge(
305 self::$mergeableMapKeys,
306 self::$mergeableListKeys,
307 self::$mergeableAliasListKeys,
308 self::$optionalMergeKeys,
313 return isset( $this->mergeableKeys[$key] );
326 if ( !isset( $this->loadedItems[$code][$key] ) ) {
327 $this->loadItem( $code, $key );
330 if ( $key ===
'fallback' && isset( $this->shallowFallbacks[$code] ) ) {
331 return $this->shallowFallbacks[$code];
335 return $this->data[$code][$key];
346 if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
347 !isset( $this->loadedItems[$code][$key] )
349 $this->loadSubitem( $code, $key, $subkey );
352 return $this->data[$code][$key][$subkey] ??
null;
365 $subitem = $this->getSubitem( $code, $key, $subkey );
367 if ( $subitem ===
null ) {
372 return [ $subitem, $this->sourceLanguage[$code][$key][$subkey] ?? $code ];
388 if ( in_array( $key, self::$splitKeys ) ) {
389 return $this->getSubitem( $code,
'list', $key );
391 $item = $this->getItem( $code, $key );
392 if ( is_array( $item ) ) {
393 return array_keys( $item );
406 if ( !isset( $this->initialisedLangs[$code] ) ) {
407 $this->initLanguage( $code );
411 if ( isset( $this->loadedItems[$code][$key] ) ) {
415 if ( isset( $this->shallowFallbacks[$code] ) ) {
416 $this->loadItem( $this->shallowFallbacks[$code], $key );
421 if ( in_array( $key, self::$splitKeys ) ) {
422 $subkeyList = $this->getSubitem( $code,
'list', $key );
423 foreach ( $subkeyList as $subkey ) {
424 if ( isset( $this->data[$code][$key][$subkey] ) ) {
427 $this->loadSubitem( $code, $key, $subkey );
430 $this->data[$code][$key] = $this->store->get( $code, $key );
433 $this->loadedItems[$code][$key] =
true;
443 if ( !in_array( $key, self::$splitKeys ) ) {
444 $this->loadItem( $code, $key );
449 if ( !isset( $this->initialisedLangs[$code] ) ) {
450 $this->initLanguage( $code );
454 if ( isset( $this->loadedItems[$code][$key] ) ||
455 isset( $this->loadedSubitems[$code][$key][$subkey] )
460 if ( isset( $this->shallowFallbacks[$code] ) ) {
461 $this->loadSubitem( $this->shallowFallbacks[$code], $key, $subkey );
466 $value = $this->store->get( $code,
"$key:$subkey" );
467 if ( $value !==
null && in_array( $key, self::$sourcePrefixKeys ) ) {
469 $this->sourceLanguage[$code][$key][$subkey],
470 $this->data[$code][$key][$subkey]
471 ] = explode( self::SOURCEPREFIX_SEPARATOR, $value, 2 );
473 $this->data[$code][$key][$subkey] = $value;
476 $this->loadedSubitems[$code][$key][$subkey] =
true;
487 if ( $this->options->get(
'forceRecache' ) && !isset( $this->recachedLangs[$code] ) ) {
488 $this->logger->debug( __METHOD__ .
"($code): forced reload" );
493 $deps = $this->store->get( $code,
'deps' );
494 $keys = $this->store->get( $code,
'list' );
495 $preload = $this->store->get( $code,
'preload' );
497 if ( $deps ===
null ||
$keys ===
null || $preload ===
null ) {
498 $this->logger->debug( __METHOD__ .
"($code): cache missing, need to make one" );
503 foreach ( $deps as $dep ) {
509 $this->logger->debug( __METHOD__ .
"($code): cache for $code expired due to " .
525 if ( isset( $this->initialisedLangs[$code] ) ) {
529 $this->initialisedLangs[$code] =
true;
531 # If the code is of the wrong form for a Messages*.php file, do a shallow fallback
532 if ( !$this->langNameUtils->isValidBuiltInCode( $code ) ) {
533 $this->initShallowFallback( $code,
'en' );
538 # Recache the data if necessary
539 if ( !$this->manualRecache && $this->isExpired( $code ) ) {
540 if ( $this->langNameUtils->isSupportedLanguage( $code ) ) {
541 $this->recache( $code );
542 } elseif ( $code ===
'en' ) {
543 throw new MWException(
'MessagesEn.php is missing.' );
545 $this->initShallowFallback( $code,
'en' );
552 $preload = $this->getItem( $code,
'preload' );
553 if ( $preload ===
null ) {
554 if ( $this->manualRecache ) {
556 if ( $code ===
'en' ) {
557 throw new MWException(
'No localisation cache found for English. ' .
558 'Please run maintenance/rebuildLocalisationCache.php.' );
560 $this->initShallowFallback( $code,
'en' );
564 throw new MWException(
'Invalid or missing localisation cache.' );
568 foreach ( self::$sourcePrefixKeys as $key ) {
569 if ( !isset( $preload[$key] ) ) {
572 foreach ( $preload[$key] as $subkey => $value ) {
573 if ( $value !==
null ) {
575 $this->sourceLanguage[$code][$key][$subkey],
576 $preload[$key][$subkey]
577 ] = explode( self::SOURCEPREFIX_SEPARATOR, $value, 2 );
579 $preload[$key][$subkey] =
null;
584 $this->data[$code] = $preload;
585 foreach ( $preload as $key => $item ) {
586 if ( in_array( $key, self::$splitKeys ) ) {
587 foreach ( $item as $subkey => $subitem ) {
588 $this->loadedSubitems[$code][$key][$subkey] =
true;
591 $this->loadedItems[$code][$key] =
true;
603 $this->data[$primaryCode] =& $this->data[$fallbackCode];
604 $this->loadedItems[$primaryCode] =& $this->loadedItems[$fallbackCode];
605 $this->loadedSubitems[$primaryCode] =& $this->loadedSubitems[$fallbackCode];
606 $this->shallowFallbacks[$primaryCode] = $fallbackCode;
620 if ( $_fileType ==
'core' || $_fileType ==
'extension' ) {
621 foreach ( self::$allKeys as $key ) {
624 if ( isset( $$key ) ) {
628 } elseif ( $_fileType ==
'aliases' ) {
630 if ( isset( $aliases ) ) {
631 $data[
'aliases'] = $aliases;
634 throw new MWException( __METHOD__ .
": Invalid file type: $_fileType" );
647 if ( !is_readable( $fileName ) ) {
651 $json = file_get_contents( $fileName );
652 if ( $json ===
false ) {
656 $data = FormatJson::decode( $json,
true );
657 if ( $data ===
null ) {
658 throw new MWException( __METHOD__ .
": Invalid JSON file: $fileName" );
662 foreach ( $data as $key => $unused ) {
663 if ( $key ===
'' || $key[0] ===
'@' ) {
664 unset( $data[$key] );
678 $rules = $this->getPluralRules( $code );
679 if ( $rules ===
null ) {
683 $compiledRules = Evaluator::compile( $rules );
684 }
catch ( CLDRPluralRuleError $e ) {
685 $this->logger->debug( $e->getMessage() );
690 return $compiledRules;
701 if ( $this->pluralRules ===
null ) {
702 $this->loadPluralFiles();
704 return $this->pluralRules[$code] ??
null;
715 if ( $this->pluralRuleTypes ===
null ) {
716 $this->loadPluralFiles();
718 return $this->pluralRuleTypes[$code] ??
null;
725 foreach ( $this->getPluralFiles() as $fileName ) {
726 $this->loadPluralFile( $fileName );
730 private function getPluralFiles(): array {
734 "$IP/languages/data/plurals.xml",
736 "$IP/languages/data/plurals-mediawiki.xml",
749 $xml = file_get_contents( $fileName );
751 throw new MWException(
"Unable to read plurals file $fileName" );
753 $doc =
new DOMDocument;
754 $doc->loadXML( $xml );
755 $rulesets = $doc->getElementsByTagName(
"pluralRules" );
756 foreach ( $rulesets as $ruleset ) {
757 $codes = $ruleset->getAttribute(
'locales' );
760 $ruleElements = $ruleset->getElementsByTagName(
"pluralRule" );
761 foreach ( $ruleElements as $elt ) {
762 $ruleType = $elt->getAttribute(
'count' );
763 if ( $ruleType ===
'other' ) {
767 $rules[] = $elt->nodeValue;
768 $ruleTypes[] = $ruleType;
770 foreach ( explode(
' ', $codes ) as $code ) {
771 $this->pluralRules[$code] = $rules;
772 $this->pluralRuleTypes[$code] = $ruleTypes;
788 $fileName = $this->langNameUtils->getMessagesFileName( $code );
789 if ( !is_file( $fileName ) ) {
793 $data = $this->readPHPFile( $fileName,
'core' );
797 $data[
'pluralRules'] = $this->getPluralRules( $code );
799 $data[
'compiledPluralRules'] = $this->getCompiledPluralRules( $code );
801 $data[
'pluralRuleTypes'] = $this->getPluralRuleTypes( $code );
803 foreach ( $this->getPluralFiles() as $fileName ) {
817 protected function mergeItem( $key, &$value, $fallbackValue ) {
818 if ( $value !==
null ) {
819 if ( $fallbackValue !==
null ) {
820 if ( in_array( $key, self::$mergeableMapKeys ) ) {
821 $value += $fallbackValue;
822 } elseif ( in_array( $key, self::$mergeableListKeys ) ) {
823 $value = array_unique( array_merge( $fallbackValue, $value ) );
824 } elseif ( in_array( $key, self::$mergeableAliasListKeys ) ) {
825 $value = array_merge_recursive( $value, $fallbackValue );
826 } elseif ( in_array( $key, self::$optionalMergeKeys ) ) {
827 if ( !empty( $value[
'inherit'] ) ) {
828 $value = array_merge( $fallbackValue, $value );
831 unset( $value[
'inherit'] );
832 } elseif ( in_array( $key, self::$magicWordKeys ) ) {
833 $this->mergeMagicWords( $value, $fallbackValue );
837 $value = $fallbackValue;
846 foreach ( $fallbackValue as $magicName => $fallbackInfo ) {
847 if ( !isset( $value[$magicName] ) ) {
848 $value[$magicName] = $fallbackInfo;
850 $oldSynonyms = array_slice( $fallbackInfo, 1 );
851 $newSynonyms = array_slice( $value[$magicName], 1 );
852 $synonyms = array_values( array_unique( array_merge(
853 $newSynonyms, $oldSynonyms ) ) );
854 $value[$magicName] = array_merge( [ $fallbackInfo[0] ], $synonyms );
870 'core' =>
"$IP/languages/i18n",
871 'exif' =>
"$IP/languages/i18n/exif",
872 'api' =>
"$IP/includes/api/i18n",
873 'rest' =>
"$IP/includes/Rest/i18n",
874 'oojs-ui' =>
"$IP/resources/lib/ooui/i18n",
875 'paramvalidator' =>
"$IP/includes/libs/ParamValidator/i18n",
876 ] + $this->options->get( MainConfigNames::MessagesDirs );
887 throw new MWException(
"Invalid language code requested" );
889 $this->recachedLangs[ $code ] =
true;
892 $initialData = array_fill_keys( self::$allKeys,
null );
893 $coreData = $initialData;
896 # Load the primary localisation from the source file
897 $data = $this->readSourceFilesAndRegisterDeps( $code, $deps );
898 $this->logger->debug( __METHOD__ .
": got localisation for $code from source" );
900 # Merge primary localisation
901 foreach ( $data as $key => $value ) {
902 $this->mergeItem( $key, $coreData[ $key ], $value );
905 # Fill in the fallback if it's not there already
907 if ( ( $coreData[
'fallback'] ===
null || $coreData[
'fallback'] ===
false ) && $code ===
'en' ) {
908 $coreData[
'fallback'] =
false;
909 $coreData[
'originalFallbackSequence'] = $coreData[
'fallbackSequence'] = [];
911 if ( $coreData[
'fallback'] !==
null ) {
912 $coreData[
'fallbackSequence'] = array_map(
'trim', explode(
',', $coreData[
'fallback'] ) );
914 $coreData[
'fallbackSequence'] = [];
916 $len = count( $coreData[
'fallbackSequence'] );
918 # Before we add the 'en' fallback for messages, keep a copy of
919 # the original fallback sequence
920 $coreData[
'originalFallbackSequence'] = $coreData[
'fallbackSequence'];
922 # Ensure that the sequence ends at 'en' for messages
923 if ( !$len || $coreData[
'fallbackSequence'][$len - 1] !==
'en' ) {
924 $coreData[
'fallbackSequence'][] =
'en';
928 $codeSequence = array_merge( [ $code ], $coreData[
'fallbackSequence'] );
929 $messageDirs = $this->getMessagesDirs();
931 # Load non-JSON localisation data for extensions
932 $extensionData = array_fill_keys( $codeSequence, $initialData );
933 foreach ( $this->options->get( MainConfigNames::ExtensionMessagesFiles ) as $extension => $fileName ) {
934 if ( isset( $messageDirs[$extension] ) ) {
935 # This extension has JSON message data; skip the PHP shim
939 $data = $this->readPHPFile( $fileName,
'extension' );
942 foreach ( $data as $key => $item ) {
943 foreach ( $codeSequence as $csCode ) {
944 if ( isset( $item[$csCode] ) ) {
947 if ( in_array( $key, self::$sourcePrefixKeys ) ) {
948 foreach ( $item[$csCode] as $subkey => $_ ) {
949 $this->sourceLanguage[$code][$key][$subkey] ??= $csCode;
952 $this->mergeItem( $key, $extensionData[$csCode][$key], $item[$csCode] );
963 # Load the localisation data for each fallback, then merge it into the full array
964 $allData = $initialData;
965 foreach ( $codeSequence as $csCode ) {
966 $csData = $initialData;
968 # Load core messages and the extension localisations.
969 foreach ( $messageDirs as $dirs ) {
970 foreach ( (array)$dirs as $dir ) {
971 $fileName =
"$dir/$csCode.json";
972 $messages = $this->readJSONFile( $fileName );
974 foreach ( $messages as $subkey => $_ ) {
975 $this->sourceLanguage[$code][
'messages'][$subkey] ??= $csCode;
977 $this->mergeItem(
'messages', $csData[
'messages'], $messages );
983 # Merge non-JSON extension data
984 if ( isset( $extensionData[$csCode] ) ) {
985 foreach ( $extensionData[$csCode] as $key => $item ) {
986 $this->mergeItem( $key, $csData[$key], $item );
990 if ( $csCode === $code ) {
991 # Merge core data into extension data
992 foreach ( $coreData as $key => $item ) {
993 $this->mergeItem( $key, $csData[$key], $item );
996 # Load the secondary localisation from the source file to
997 # avoid infinite cycles on cyclic fallbacks
998 $fbData = $this->readSourceFilesAndRegisterDeps( $csCode, $deps );
999 # Only merge the keys that make sense to merge
1000 foreach ( self::$allKeys as $key ) {
1001 if ( !isset( $fbData[ $key ] ) ) {
1005 if ( ( $coreData[ $key ] ) ===
null || $this->isMergeableKey( $key ) ) {
1006 $this->mergeItem( $key, $csData[ $key ], $fbData[ $key ] );
1011 # Allow extensions an opportunity to adjust the data for this
1013 $this->hookRunner->onLocalisationCacheRecacheFallback( $this, $csCode, $csData );
1015 # Merge the data for this fallback into the final array
1016 if ( $csCode === $code ) {
1019 foreach ( self::$allKeys as $key ) {
1020 if ( !isset( $csData[$key] ) ) {
1025 if ( $allData[$key] ===
null || $this->isMergeableKey( $key ) ) {
1026 $this->mergeItem( $key, $allData[$key], $csData[$key] );
1032 if ( !isset( $allData[
'rtl'] ) ) {
1033 throw new MWException( __METHOD__ .
': Localisation data failed validation check! ' .
1034 'Check that your languages/messages/MessagesEn.php file is intact.' );
1037 # Add cache dependencies for any referenced globals
1038 $deps[
'wgExtensionMessagesFiles'] =
new GlobalDependency(
'wgExtensionMessagesFiles' );
1044 # Add dependencies to the cache entry
1045 $allData[
'deps'] = $deps;
1047 # Replace spaces with underscores in namespace names
1048 $allData[
'namespaceNames'] = str_replace(
' ',
'_', $allData[
'namespaceNames'] );
1050 # And do the same for special page aliases. $page is an array.
1051 foreach ( $allData[
'specialPageAliases'] as &$page ) {
1052 $page = str_replace(
' ',
'_', $page );
1054 # Decouple the reference to prevent accidental damage
1057 # If there were no plural rules, return an empty array
1058 $allData[
'pluralRules'] ??= [];
1059 $allData[
'compiledPluralRules'] ??= [];
1060 # If there were no plural rule types, return an empty array
1061 $allData[
'pluralRuleTypes'] ??= [];
1064 $allData[
'list'] = [];
1065 foreach ( self::$splitKeys as $key ) {
1066 $allData[
'list'][$key] = array_keys( $allData[$key] );
1070 $this->hookRunner->onLocalisationCacheRecache( $this, $code, $allData, $unused );
1072 # Save to the process cache and register the items loaded
1073 $this->data[$code] = $allData;
1074 foreach ( $allData as $key => $item ) {
1075 $this->loadedItems[$code][$key] =
true;
1078 # Prefix each item with its source language code before save
1079 foreach ( self::$sourcePrefixKeys as $key ) {
1081 foreach ( $allData[$key] as $subKey => $value ) {
1083 $allData[$key][$subKey] = ( $this->sourceLanguage[$code][$key][$subKey] ?? $code ) .
1084 self::SOURCEPREFIX_SEPARATOR . $value;
1088 # Set the preload key
1089 $allData[
'preload'] = $this->buildPreload( $allData );
1091 # Save to the persistent cache
1092 $this->store->startWrite( $code );
1093 foreach ( $allData as $key => $value ) {
1094 if ( in_array( $key, self::$splitKeys ) ) {
1095 foreach ( $value as $subkey => $subvalue ) {
1096 $this->store->set(
"$key:$subkey", $subvalue );
1099 $this->store->set( $key, $value );
1102 $this->store->finishWrite();
1104 # Clear out the MessageBlobStore
1105 # HACK: If using a null (i.e. disabled) storage backend, we
1106 # can't write to the MessageBlobStore either
1108 foreach ( $this->clearStoreCallbacks as $callback ) {
1123 $preload = [
'messages' => [] ];
1124 foreach ( self::$preloadedKeys as $key ) {
1125 $preload[$key] = $data[$key];
1128 foreach ( $data[
'preloadedMessages'] as $subkey ) {
1129 $subitem = $data[
'messages'][$subkey] ??
null;
1130 $preload[
'messages'][$subkey] = $subitem;
1142 unset( $this->data[$code] );
1143 unset( $this->loadedItems[$code] );
1144 unset( $this->loadedSubitems[$code] );
1145 unset( $this->initialisedLangs[$code] );
1146 unset( $this->shallowFallbacks[$code] );
1147 unset( $this->sourceLanguage[$code] );
1149 foreach ( $this->shallowFallbacks as $shallowCode => $fbCode ) {
1150 if ( $fbCode === $code ) {
1151 $this->unload( $shallowCode );
1160 foreach ( $this->initialisedLangs as
$lang => $unused ) {
1161 $this->unload(
$lang );
1170 $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, \MediaWiki\MainConfigSchema::LocalisationCacheConf.
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.
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