CLDR plural parser in PHP
[lhc/web/wiklou.git] / includes / LocalisationCache.php
index c9dd697..c1ac848 100644 (file)
@@ -154,10 +154,11 @@ class LocalisationCache {
         */
        static public $preloadedKeys = array( 'dateFormats', 'namespaceNames' );
 
-       /*
-        * Associative array containing plural rules.
+       /**
+        * Associative array of cached plural rules. The key is the language code,
+        * the value is an array of plural rules for that language.
         */
-       var $pluralRules = array();
+       var $pluralRules = null;
 
        var $mergeableKeys = null;
 
@@ -207,7 +208,6 @@ class LocalisationCache {
                                $this->$var = $conf[$var];
                        }
                }
-               $this->readPluralRules();
        }
 
        /**
@@ -491,36 +491,62 @@ class LocalisationCache {
                }
                return $data;
        }
+
        /**
-        * Read the plural rule xml files.
-        * First the CLDR xml will be read and it will be extended with
-        * mediawiki specific tailoring.
+        * Get the compiled plural rules for a given language from the XML files.
         * @since 1.20
         */
-       protected function readPluralRules() {
-               $CLDRPlural = __DIR__ . "/../languages/data/plurals.xml";
-               $MWPlural = __DIR__ . "/../languages/data/plurals-mediawiki.xml";
-               # Load CLDR plural rules
-               $this->parsePluralXML( $CLDRPlural );
-               if ( file_exists( $MWPlural ) ) {
-                       // override or extend.
-                       $this->parsePluralXML( $MWPlural );
+       public function getCompiledPluralRules( $code ) {
+               $rules = $this->getPluralRules( $code );
+               try {
+                       $compiledRules = CLDRPluralRuleEvaluator::compile( $rules );
+               } catch( CLDRPluralRuleError $e ) {
+                       wfDebugLog( 'l10n', $e->getMessage() . "\n" );
+                       return array();
                }
+               return $compiledRules;
        }
 
-       private function parsePluralXML( $xmlFile ) {
-               $pluraldoc = new DOMDocument();
-               $pluraldoc->load( $xmlFile );
-               $rulesets = $pluraldoc->getElementsByTagName( "pluralRules" );
+       /**
+        * Get the plural rules for a given language from the XML files.
+        * Cached.
+        * @since 1.20
+        */
+       public function getPluralRules( $code ) {
+               if ( $this->pluralRules === null ) {
+                       $cldrPlural = __DIR__ . "/../languages/data/plurals.xml";
+                       $mwPlural = __DIR__ . "/../languages/data/plurals-mediawiki.xml";
+                       // Load CLDR plural rules
+                       $this->loadPluralFile( $cldrPlural );
+                       if ( file_exists( $mwPlural ) ) {
+                               // Override or extend
+                               $this->loadPluralFile( $mwPlural );
+                       }
+               }
+               if ( !isset( $this->pluralRules[$code] ) ) {
+                       return array();
+               } else {
+                       return $this->pluralRules[$code];
+               }
+       }
+
+       /**
+        * Load a plural XML file with the given filename, compile the relevant
+        * rules, and save the compiled rules in a process-local cache.
+        */
+       private function loadPluralFile( $fileName ) {
+               $doc = new DOMDocument;
+               $doc->load( $fileName );
+               $rulesets = $doc->getElementsByTagName( "pluralRules" );
                foreach ( $rulesets as $ruleset ) {
                        $codes = $ruleset->getAttribute( 'locales' );
-                       $parsedRules = array();
-                       $rules = $ruleset->getElementsByTagName( "pluralRule" );
-                       foreach ( $rules as $rule ) {
-                               $parsedRules[$rule->getAttribute( 'count' )] = $rule->nodeValue;
+                       $rules = array();
+                       $ruleElements = $ruleset->getElementsByTagName( "pluralRule" );
+                       foreach ( $ruleElements as $elt ) {
+                               $rules[] = $elt->nodeValue;
                        }
                        foreach ( explode( ' ', $codes ) as $code ) {
-                               $this->pluralRules[$code] = $parsedRules;
+                               $this->pluralRules[$code] = $rules;
                        }
                }
        }
@@ -728,10 +754,10 @@ class LocalisationCache {
                foreach ( self::$splitKeys as $key ) {
                        $allData['list'][$key] = array_keys( $allData[$key] );
                }
-               # Load CLDR plural rules
-               if ( isset( $this->pluralRules[$code] ) ) {
-                       $allData['pluralRules'] = $this->pluralRules[$code];
-               }
+               # Load CLDR plural rules for JavaScript
+               $allData['pluralRules'] = $this->getPluralRules( $code );
+               # And for PHP
+               $allData['compiledPluralRules'] = $this->getCompiledPluralRules( $code );
                # Run hooks
                wfRunHooks( 'LocalisationCacheRecache', array( $this, $code, &$allData ) );