IcuCollation: Sort digits under localised digits' headings
authorBartosz Dziewoński <matma.rex@gmail.com>
Sat, 12 Oct 2013 22:21:01 +0000 (00:21 +0200)
committerTim Starling <tstarling@wikimedia.org>
Thu, 12 Dec 2013 04:39:39 +0000 (04:39 +0000)
Previously both '1' and '۱' ("DIGIT ONE" and "EXTENDED ARABIC-INDIC
DIGIT ONE") were sorted under '1' heading, regardless of collation
locale.

Now they will be both sorted under localised heading name (transformed
using Language#formatNum), for example '1' for 'uca-en' collation or
'۱' for 'uca-fa' collation.

Bug: 55630
Change-Id: I0b745d955a6e72f53873c95648087aa5f90a8852

includes/Collation.php

index ac2187c..b0688f5 100644 (file)
@@ -149,9 +149,9 @@ class IdentityCollation extends Collation {
 }
 
 class IcuCollation extends Collation {
-       const FIRST_LETTER_VERSION = 1;
+       const FIRST_LETTER_VERSION = 2;
 
-       var $primaryCollator, $mainCollator, $locale;
+       var $primaryCollator, $mainCollator, $locale, $digitTransformLanguage;
        var $firstLetterData;
 
        /**
@@ -284,7 +284,12 @@ class IcuCollation extends Collation {
                        throw new MWException( 'An ICU collation was requested, ' .
                                'but the intl extension is not available.' );
                }
+
                $this->locale = $locale;
+               // Drop everything after the '@' in locale's name
+               $localeParts = explode( '@', $locale );
+               $this->digitTransformLanguage = Language::factory( $locale === 'root' ? 'en' : $localeParts[0] );
+
                $this->mainCollator = Collator::create( $locale );
                if ( !$this->mainCollator ) {
                        throw new MWException( "Invalid ICU locale specified for collation: $locale" );
@@ -365,6 +370,12 @@ class IcuCollation extends Collation {
                        if ( isset( self::$tailoringFirstLetters['-' . $this->locale] ) ) {
                                $letters = array_diff( $letters, self::$tailoringFirstLetters['-' . $this->locale] );
                        }
+                       // Apply digit transforms
+                       $digits = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' );
+                       $letters = array_diff( $letters, $digits );
+                       foreach ( $digits as $digit ) {
+                               $letters[] = $this->digitTransformLanguage->formatNum( $digit, true );
+                       }
                } else {
                        $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
                        if ( $letters === false ) {