Merge "TimeAdjustTest: Use dataProvider"
[lhc/web/wiklou.git] / includes / Collation.php
index 87afc10..3f0fa7b 100644 (file)
@@ -148,8 +148,9 @@ class IdentityCollation extends Collation {
        }
 }
 
-
 class IcuCollation extends Collation {
+       const FIRST_LETTER_VERSION = 1;
+
        var $primaryCollator, $mainCollator, $locale;
        var $firstLetterData;
 
@@ -181,35 +182,57 @@ class IcuCollation extends Collation {
        );
 
        /**
-        * Additional characters (or character groups) to be considered first-letters
+        * Additional characters (or character groups) to be considered separate
+        * letters for given languages, or to be removed from the list of such
+        * letters (denoted by keys starting with '-').
+        *
+        * These are additions to (or subtractions from) the data stored in the
+        * first-letters-root.ser file (which among others includes full basic latin,
+        * cyrillic and greek alphabets).
         *
-        * Generated based on the primary level of Unicode collation tailorings
-        * available at http://developer.mimer.com/charts/tailorings.htm .
+        * "Separate letter" is a letter that would have a separate heading/section
+        * for it in a dictionary or a phone book in this language. This data isn't
+        * used for sorting (the ICU library handles that), only for deciding which
+        * characters (or character groups) to use as headings.
+        *
+        * Initially generated based on the primary level of Unicode collation
+        * tailorings available at http://developer.mimer.com/charts/tailorings.htm ,
+        * later modified.
         *
         * Empty arrays are intended; this signifies that the data for the language is
         * available and that there are, in fact, no additional letters to consider.
         */
        static $tailoringFirstLetters = array(
                // Verified by native speakers
-               'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
+               'be' => array( "Ё" ),
+               'be-tarask' => array( "Ё" ),
+               'en' => array(),
                'fi' => array( "Å", "Ä", "Ö" ),
+               '-fi' => array( "Ǥ", "Ŋ", "Ŧ", "Ʒ" ), // sorted like G, N, T, Z - bug 46330
+               'hu' => array( "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ),
+               'it' => array(),
+               'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
+               'pt' => array(),
+               'ru' => array(),
+               'sv' => array( "Å", "Ä", "Ö" ),
+               '-sv' => array( "Þ" ), // sorted as "th" in Swedish, causing unexpected output - bug 45446
+               'uk' => array( "Ґ", "Ь" ),
+               'vi' => array( "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ),
                // Not verified, but likely correct
                'af' => array(),
-               'ast' => array( "CH", "LL", "Ñ" ),
+               'ast' => array( "Ch", "Ll", "Ñ" ),
                'az' => array( "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ),
-               'be' => array( "Ё" ),
                'bg' => array(),
-               'br' => array( "CH", "C'H" ),
-               'bs' => array( "Ä\8c", "Ä\86", "DŽ", "Ä\90", "LJ", "NJ", "Š", "Ž" ),
+               'br' => array( "Ch", "C'h" ),
+               'bs' => array( "Ä\8c", "Ä\86", "Dž", "Ä\90", "Lj", "Nj", "Š", "Ž" ),
                'ca' => array(),
                'co' => array(),
-               'cs' => array( "Č", "CH", "Ř", "Š", "Ž" ),
-               'cy' => array( "CH", "DD", "FF", "NG", "LL", "PH", "RH", "TH" ),
+               'cs' => array( "Č", "Ch", "Ř", "Š", "Ž" ),
+               'cy' => array( "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ),
                'da' => array( "Æ", "Ø", "Å" ),
                'de' => array(),
-               'dsb' => array( "Ä\8c", "Ä\86", "DŹ", "Ä\9a", "CH", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ),
+               'dsb' => array( "Ä\8c", "Ä\86", "Dź", "Ä\9a", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ),
                'el' => array(),
-               'en' => array(),
                'eo' => array( "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ),
                'es' => array( "Ñ" ),
                'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü" ),
@@ -220,12 +243,10 @@ class IcuCollation extends Collation {
                'fy' => array(),
                'ga' => array(),
                'gd' => array(),
-               'gl' => array( "CH", "LL", "Ñ" ),
-               'hr' => array( "Č", "Ć", "DŽ", "Đ", "LJ", "NJ", "Š", "Ž" ),
-               'hsb' => array( "Č", "DŹ", "Ě", "CH", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ),
-               'hu' => array( "CS", "DZ", "DZS", "GY", "LY", "NY", "Ö", "SZ", "TY", "Ü", "ZS" ),
+               'gl' => array( "Ch", "Ll", "Ñ" ),
+               'hr' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
+               'hsb' => array( "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ),
                'is' => array( "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ),
-               'it' => array(),
                'kk' => array( "Ү", "І" ),
                'kl' => array( "Æ", "Ø", "Å" ),
                'ku' => array( "Ç", "Ê", "Î", "Ş", "Û" ),
@@ -236,29 +257,24 @@ class IcuCollation extends Collation {
                'lv' => array( "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ),
                'mk' => array(),
                'mo' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
-               'mt' => array( "Ä\8a", "Ä ", "GĦ", "Ħ", "Ż" ),
+               'mt' => array( "Ä\8a", "Ä ", "Għ", "Ħ", "Ż" ),
                'nl' => array(),
                'no' => array( "Æ", "Ø", "Å" ),
                'oc' => array(),
-               'pt' => array(),
                'rm' => array(),
                'ro' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
-               'ru' => array(),
                'rup' => array( "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ),
                'sco' => array(),
-               'sk' => array( "Ä", "Č", "CH", "Ô", "Š", "Ž" ),
+               'sk' => array( "Ä", "Č", "Ch", "Ô", "Š", "Ž" ),
                'sl' => array( "Č", "Š", "Ž" ),
                'smn' => array( "Á", "Č", "Đ", "Ŋ", "Š", "Ŧ", "Ž", "Æ", "Ø", "Å", "Ä", "Ö" ),
-               'sq' => array( "Ç", "DH", "Ë", "GJ", "LL", "NJ", "RR", "SH", "TH", "XH", "ZH" ),
+               'sq' => array( "Ç", "Dh", "Ë", "Gj", "Ll", "Nj", "Rr", "Sh", "Th", "Xh", "Zh" ),
                'sr' => array(),
-               'sv' => array( "Å", "Ä", "Ö" ),
                'tk' => array( "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ),
-               'tl' => array( "Ñ", "NG" ), /* 'fil' in the data source */
+               'tl' => array( "Ñ", "Ng" ),
                'tr' => array( "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ),
                'tt' => array( "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ),
-               'uk' => array( "Ґ", "Ь" ),
-               'uz' => array( "CH", "G'", "NG", "O'", "SH" ),
-               'vi' => array( "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ),
+               'uz' => array( "Ch", "G'", "Ng", "O'", "Sh" ),
        );
 
        const RECORD_LENGTH = 14;
@@ -334,7 +350,9 @@ class IcuCollation extends Collation {
                $cacheKey = wfMemcKey( 'first-letters', $this->locale );
                $cacheEntry = $cache->get( $cacheKey );
 
-               if ( $cacheEntry ) {
+               if ( $cacheEntry && isset( $cacheEntry['version'] )
+                       && $cacheEntry['version'] == self::FIRST_LETTER_VERSION ) 
+               {
                        $this->firstLetterData = $cacheEntry;
                        return $this->firstLetterData;
                }
@@ -343,7 +361,12 @@ class IcuCollation extends Collation {
 
                if ( isset ( self::$tailoringFirstLetters[$this->locale] ) ) {
                        $letters = wfGetPrecompiledData( "first-letters-root.ser" );
+                       // Append additional characters
                        $letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
+                       // Remove unnecessary ones, if any
+                       if ( isset( self::$tailoringFirstLetters[ '-' . $this->locale ] ) ) {
+                               $letters = array_diff( $letters, self::$tailoringFirstLetters[ '-' . $this->locale ] );
+                       }
                } else {
                        $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
                        if ( $letters === false ) {
@@ -376,7 +399,8 @@ class IcuCollation extends Collation {
                ksort( $letterMap, SORT_STRING );
                $data = array(
                        'chars' => array_values( $letterMap ),
-                       'keys' => array_keys( $letterMap )
+                       'keys' => array_keys( $letterMap ),
+                       'version' => self::FIRST_LETTER_VERSION,
                );
 
                // Reduce memory usage before caching
@@ -413,13 +437,13 @@ class IcuCollation extends Collation {
         * Do a binary search, and return the index of the largest item that sorts
         * less than or equal to the target value.
         *
-        * @param $valueCallback array A function to call to get the value with
+        * @param array $valueCallback A function to call to get the value with
         *     a given array index.
-        * @param $valueCount int The number of items accessible via $valueCallback,
+        * @param int $valueCount The number of items accessible via $valueCallback,
         *     indexed from 0 to $valueCount - 1
-        * @param $comparisonCallback array A callback to compare two values, returning
+        * @param array $comparisonCallback A callback to compare two values, returning
         *     -1, 0 or 1 in the style of strcmp().
-        * @param $target string The target value to find.
+        * @param string $target The target value to find.
         *
         * @return int|bool The item index of the lower bound, or false if the target value
         *     sorts before all items.