MediaWiki  1.23.12
Collation.php
Go to the documentation of this file.
1 <?php
23 abstract class Collation {
24  static $instance;
25 
29  static function singleton() {
30  if ( !self::$instance ) {
31  global $wgCategoryCollation;
32  self::$instance = self::factory( $wgCategoryCollation );
33  }
34  return self::$instance;
35  }
36 
42  static function factory( $collationName ) {
43  switch ( $collationName ) {
44  case 'uppercase':
45  return new UppercaseCollation;
46  case 'identity':
47  return new IdentityCollation;
48  case 'uca-default':
49  return new IcuCollation( 'root' );
50  case 'xx-uca-ckb':
51  return new CollationCkb;
52  default:
53  $match = array();
54  if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
55  return new IcuCollation( $match[1] );
56  }
57 
58  # Provide a mechanism for extensions to hook in.
59  $collationObject = null;
60  wfRunHooks( 'Collation::factory', array( $collationName, &$collationObject ) );
61 
62  if ( $collationObject instanceof Collation ) {
63  return $collationObject;
64  }
65 
66  // If all else fails...
67  throw new MWException( __METHOD__ . ": unknown collation type \"$collationName\"" );
68  }
69  }
70 
82  abstract function getSortKey( $string );
83 
107  abstract function getFirstLetter( $string );
108 }
109 
111  var $lang;
112  function __construct() {
113  // Get a language object so that we can use the generic UTF-8 uppercase
114  // function there
115  $this->lang = Language::factory( 'en' );
116  }
117 
118  function getSortKey( $string ) {
119  return $this->lang->uc( $string );
120  }
121 
122  function getFirstLetter( $string ) {
123  if ( $string[0] == "\0" ) {
124  $string = substr( $string, 1 );
125  }
126  return $this->lang->ucfirst( $this->lang->firstChar( $string ) );
127  }
128 }
129 
137 
138  function getSortKey( $string ) {
139  return $string;
140  }
141 
142  function getFirstLetter( $string ) {
144  // Copied from UppercaseCollation.
145  // I'm kind of unclear on when this could happen...
146  if ( $string[0] == "\0" ) {
147  $string = substr( $string, 1 );
148  }
149  return $wgContLang->firstChar( $string );
150  }
151 }
152 
153 class IcuCollation extends Collation {
155 
158 
168  static $cjkBlocks = array(
169  array( 0x2E80, 0x2EFF ), // CJK Radicals Supplement
170  array( 0x2F00, 0x2FDF ), // Kangxi Radicals
171  array( 0x2FF0, 0x2FFF ), // Ideographic Description Characters
172  array( 0x3000, 0x303F ), // CJK Symbols and Punctuation
173  array( 0x31C0, 0x31EF ), // CJK Strokes
174  array( 0x3200, 0x32FF ), // Enclosed CJK Letters and Months
175  array( 0x3300, 0x33FF ), // CJK Compatibility
176  array( 0x3400, 0x4DBF ), // CJK Unified Ideographs Extension A
177  array( 0x4E00, 0x9FFF ), // CJK Unified Ideographs
178  array( 0xF900, 0xFAFF ), // CJK Compatibility Ideographs
179  array( 0xFE30, 0xFE4F ), // CJK Compatibility Forms
180  array( 0x20000, 0x2A6DF ), // CJK Unified Ideographs Extension B
181  array( 0x2A700, 0x2B73F ), // CJK Unified Ideographs Extension C
182  array( 0x2B740, 0x2B81F ), // CJK Unified Ideographs Extension D
183  array( 0x2F800, 0x2FA1F ), // CJK Compatibility Ideographs Supplement
184  );
185 
208  // Verified by native speakers
209  'be' => array( "Ё" ),
210  'be-tarask' => array( "Ё" ),
211  'en' => array(),
212  'fi' => array( "Å", "Ä", "Ö" ),
213  'hu' => array( "Cs", "Dz", "Dzs", "Gy", "Ly", "Ny", "Ö", "Sz", "Ty", "Ü", "Zs" ),
214  'it' => array(),
215  'pl' => array( "Ą", "Ć", "Ę", "Ł", "Ń", "Ó", "Ś", "Ź", "Ż" ),
216  'pt' => array(),
217  'ru' => array(),
218  'sv' => array( "Å", "Ä", "Ö" ),
219  'sv@collation=standard' => array( "Å", "Ä", "Ö" ),
220  'uk' => array( "Ґ", "Ь" ),
221  'vi' => array( "Ă", "Â", "Đ", "Ê", "Ô", "Ơ", "Ư" ),
222  // Not verified, but likely correct
223  'af' => array(),
224  'ast' => array( "Ch", "Ll", "Ñ" ),
225  'az' => array( "Ç", "Ə", "Ğ", "İ", "Ö", "Ş", "Ü" ),
226  'bg' => array(),
227  'br' => array( "Ch", "C'h" ),
228  'bs' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
229  'ca' => array(),
230  'co' => array(),
231  'cs' => array( "Č", "Ch", "Ř", "Š", "Ž" ),
232  'cy' => array( "Ch", "Dd", "Ff", "Ng", "Ll", "Ph", "Rh", "Th" ),
233  'da' => array( "Æ", "Ø", "Å" ),
234  'de' => array(),
235  'dsb' => array( "Č", "Ć", "Dź", "Ě", "Ch", "Ł", "Ń", "Ŕ", "Š", "Ś", "Ž", "Ź" ),
236  'el' => array(),
237  'eo' => array( "Ĉ", "Ĝ", "Ĥ", "Ĵ", "Ŝ", "Ŭ" ),
238  'es' => array( "Ñ" ),
239  'et' => array( "Š", "Ž", "Õ", "Ä", "Ö", "Ü" ),
240  'eu' => array( "Ñ" ),
241  'fa' => array( "آ", "ء", "ه" ),
242  'fo' => array( "Á", "Ð", "Í", "Ó", "Ú", "Ý", "Æ", "Ø", "Å" ),
243  'fr' => array(),
244  'fur' => array( "À", "Á", "Â", "È", "Ì", "Ò", "Ù" ),
245  'fy' => array(),
246  'ga' => array(),
247  'gd' => array(),
248  'gl' => array( "Ch", "Ll", "Ñ" ),
249  'hr' => array( "Č", "Ć", "Dž", "Đ", "Lj", "Nj", "Š", "Ž" ),
250  'hsb' => array( "Č", "Dź", "Ě", "Ch", "Ł", "Ń", "Ř", "Š", "Ć", "Ž" ),
251  'is' => array( "Á", "Ð", "É", "Í", "Ó", "Ú", "Ý", "Þ", "Æ", "Ö", "Å" ),
252  'kk' => array( "Ү", "І" ),
253  'kl' => array( "Æ", "Ø", "Å" ),
254  'ku' => array( "Ç", "Ê", "Î", "Ş", "Û" ),
255  'ky' => array( "Ё" ),
256  'la' => array(),
257  'lb' => array(),
258  'lt' => array( "Č", "Š", "Ž" ),
259  'lv' => array( "Č", "Ģ", "Ķ", "Ļ", "Ņ", "Š", "Ž" ),
260  'mk' => array(),
261  'mo' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
262  'mt' => array( "Ċ", "Ġ", "Għ", "Ħ", "Ż" ),
263  'nl' => array(),
264  'no' => array( "Æ", "Ø", "Å" ),
265  'oc' => array(),
266  'rm' => array(),
267  'ro' => array( "Ă", "Â", "Î", "Ş", "Ţ" ),
268  'rup' => array( "Ă", "Â", "Î", "Ľ", "Ń", "Ş", "Ţ" ),
269  'sco' => array(),
270  'sk' => array( "Ä", "Č", "Ch", "Ô", "Š", "Ž" ),
271  'sl' => array( "Č", "Š", "Ž" ),
272  'smn' => array( "Á", "Č", "Đ", "Ŋ", "Š", "Ŧ", "Ž", "Æ", "Ø", "Å", "Ä", "Ö" ),
273  'sq' => array( "Ç", "Dh", "Ë", "Gj", "Ll", "Nj", "Rr", "Sh", "Th", "Xh", "Zh" ),
274  'sr' => array(),
275  'tk' => array( "Ç", "Ä", "Ž", "Ň", "Ö", "Ş", "Ü", "Ý" ),
276  'tl' => array( "Ñ", "Ng" ),
277  'tr' => array( "Ç", "Ğ", "İ", "Ö", "Ş", "Ü" ),
278  'tt' => array( "Ә", "Ө", "Ү", "Җ", "Ң", "Һ" ),
279  'uz' => array( "Ch", "G'", "Ng", "O'", "Sh" ),
280  );
281 
282  const RECORD_LENGTH = 14;
283 
284  function __construct( $locale ) {
285  if ( !extension_loaded( 'intl' ) ) {
286  throw new MWException( 'An ICU collation was requested, ' .
287  'but the intl extension is not available.' );
288  }
289 
290  $this->locale = $locale;
291  // Drop everything after the '@' in locale's name
292  $localeParts = explode( '@', $locale );
293  $this->digitTransformLanguage = Language::factory( $locale === 'root' ? 'en' : $localeParts[0] );
294 
295  $this->mainCollator = Collator::create( $locale );
296  if ( !$this->mainCollator ) {
297  throw new MWException( "Invalid ICU locale specified for collation: $locale" );
298  }
299 
300  $this->primaryCollator = Collator::create( $locale );
301  $this->primaryCollator->setStrength( Collator::PRIMARY );
302  }
303 
304  function getSortKey( $string ) {
305  // intl extension produces non null-terminated
306  // strings. Appending '' fixes it so that it doesn't generate
307  // a warning on each access in debug php.
309  $key = $this->mainCollator->getSortKey( $string ) . '';
311  return $key;
312  }
313 
314  function getPrimarySortKey( $string ) {
316  $key = $this->primaryCollator->getSortKey( $string ) . '';
318  return $key;
319  }
320 
321  function getFirstLetter( $string ) {
322  $string = strval( $string );
323  if ( $string === '' ) {
324  return '';
325  }
326 
327  // Check for CJK
328  $firstChar = mb_substr( $string, 0, 1, 'UTF-8' );
329  if ( ord( $firstChar ) > 0x7f && self::isCjk( utf8ToCodepoint( $firstChar ) ) ) {
330  return $firstChar;
331  }
332 
333  $sortKey = $this->getPrimarySortKey( $string );
334 
335  // Do a binary search to find the correct letter to sort under
337  array( $this, 'getSortKeyByLetterIndex' ),
338  $this->getFirstLetterCount(),
339  'strcmp',
340  $sortKey );
341 
342  if ( $min === false ) {
343  // Before the first letter
344  return '';
345  }
346  return $this->getLetterByIndex( $min );
347  }
348 
349  function getFirstLetterData() {
350  if ( $this->firstLetterData !== null ) {
351  return $this->firstLetterData;
352  }
353 
355  $cacheKey = wfMemcKey( 'first-letters', $this->locale, $this->digitTransformLanguage->getCode() );
356  $cacheEntry = $cache->get( $cacheKey );
357 
358  if ( $cacheEntry && isset( $cacheEntry['version'] )
359  && $cacheEntry['version'] == self::FIRST_LETTER_VERSION
360  ) {
361  $this->firstLetterData = $cacheEntry;
362  return $this->firstLetterData;
363  }
364 
365  // Generate data from serialized data file
366 
367  if ( isset( self::$tailoringFirstLetters[$this->locale] ) ) {
368  $letters = wfGetPrecompiledData( "first-letters-root.ser" );
369  // Append additional characters
370  $letters = array_merge( $letters, self::$tailoringFirstLetters[$this->locale] );
371  // Remove unnecessary ones, if any
372  if ( isset( self::$tailoringFirstLetters['-' . $this->locale] ) ) {
373  $letters = array_diff( $letters, self::$tailoringFirstLetters['-' . $this->locale] );
374  }
375  // Apply digit transforms
376  $digits = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' );
377  $letters = array_diff( $letters, $digits );
378  foreach ( $digits as $digit ) {
379  $letters[] = $this->digitTransformLanguage->formatNum( $digit, true );
380  }
381  } else {
382  $letters = wfGetPrecompiledData( "first-letters-{$this->locale}.ser" );
383  if ( $letters === false ) {
384  throw new MWException( "MediaWiki does not support ICU locale " .
385  "\"{$this->locale}\"" );
386  }
387  }
388 
389  // Sort the letters.
390  //
391  // It's impossible to have the precompiled data file properly sorted,
392  // because the sort order changes depending on ICU version. If the
393  // array is not properly sorted, the binary search will return random
394  // results.
395  //
396  // We also take this opportunity to remove primary collisions.
397  $letterMap = array();
398  foreach ( $letters as $letter ) {
399  $key = $this->getPrimarySortKey( $letter );
400  if ( isset( $letterMap[$key] ) ) {
401  // Primary collision
402  // Keep whichever one sorts first in the main collator
403  if ( $this->mainCollator->compare( $letter, $letterMap[$key] ) < 0 ) {
404  $letterMap[$key] = $letter;
405  }
406  } else {
407  $letterMap[$key] = $letter;
408  }
409  }
410  ksort( $letterMap, SORT_STRING );
411  // Remove duplicate prefixes. Basically if something has a sortkey
412  // which is a prefix of some other sortkey, then it is an
413  // expansion and probably should not be considered a section
414  // header.
415  //
416  // For example 'þ' is sometimes sorted as if it is the letters
417  // 'th'. Other times it is its own primary element. Another
418  // example is '₨'. Sometimes its a currency symbol. Sometimes it
419  // is an 'R' followed by an 's'.
420  //
421  // Additionally an expanded element should always sort directly
422  // after its first element due to they way sortkeys work.
423  //
424  // UCA sortkey elements are of variable length but no collation
425  // element should be a prefix of some other element, so I think
426  // this is safe. See:
427  // * https://ssl.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm
428  // * http://site.icu-project.org/design/collation/uca-weight-allocation
429  //
430  // Additionally, there is something called primary compression to
431  // worry about. Basically, if you have two primary elements that
432  // are more than one byte and both start with the same byte then
433  // the first byte is dropped on the second primary. Additionally
434  // either \x03 or \xFF may be added to mean that the next primary
435  // does not start with the first byte of the first primary.
436  //
437  // This shouldn't matter much, as the first primary is not
438  // changed, and that is what we are comparing against.
439  //
440  // tl;dr: This makes some assumptions about how icu implements
441  // collations. It seems incredibly unlikely these assumptions
442  // will change, but nonetheless they are assumptions.
443 
444  $prev = false;
445  $duplicatePrefixes = array();
446  foreach ( $letterMap as $key => $value ) {
447  // Remove terminator byte. Otherwise the prefix
448  // comparison will get hung up on that.
449  $trimmedKey = rtrim( $key, "\0" );
450  if ( $prev === false || $prev === '' ) {
451  $prev = $trimmedKey;
452  // We don't yet have a collation element
453  // to compare against, so continue.
454  continue;
455  }
456 
457  // Due to the fact the array is sorted, we only have
458  // to compare with the element directly previous
459  // to the current element (skipping expansions).
460  // An element "X" will always sort directly
461  // before "XZ" (Unless we have "XY", but we
462  // do not update $prev in that case).
463  if ( substr( $trimmedKey, 0, strlen( $prev ) ) === $prev ) {
464  $duplicatePrefixes[] = $key;
465  // If this is an expansion, we don't want to
466  // compare the next element to this element,
467  // but to what is currently $prev
468  continue;
469  }
470  $prev = $trimmedKey;
471  }
472  foreach ( $duplicatePrefixes as $badKey ) {
473  wfDebug( "Removing '{$letterMap[$badKey]}' from first letters.\n" );
474  unset( $letterMap[$badKey] );
475  // This code assumes that unsetting does not change sort order.
476  }
477  $data = array(
478  'chars' => array_values( $letterMap ),
479  'keys' => array_keys( $letterMap ),
480  'version' => self::FIRST_LETTER_VERSION,
481  );
482 
483  // Reduce memory usage before caching
484  unset( $letterMap );
485 
486  // Save to cache
487  $this->firstLetterData = $data;
488  $cache->set( $cacheKey, $data, 86400 * 7 /* 1 week */ );
489  return $data;
490  }
491 
492  function getLetterByIndex( $index ) {
493  if ( $this->firstLetterData === null ) {
494  $this->getFirstLetterData();
495  }
496  return $this->firstLetterData['chars'][$index];
497  }
498 
499  function getSortKeyByLetterIndex( $index ) {
500  if ( $this->firstLetterData === null ) {
501  $this->getFirstLetterData();
502  }
503  return $this->firstLetterData['keys'][$index];
504  }
505 
506  function getFirstLetterCount() {
507  if ( $this->firstLetterData === null ) {
508  $this->getFirstLetterData();
509  }
510  return count( $this->firstLetterData['chars'] );
511  }
512 
530  function findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target ) {
531  wfDeprecated( __METHOD__, '1.23' );
532  return ArrayUtils::findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target );
533  }
534 
535  static function isCjk( $codepoint ) {
536  foreach ( self::$cjkBlocks as $block ) {
537  if ( $codepoint >= $block[0] && $codepoint <= $block[1] ) {
538  return true;
539  }
540  }
541  return false;
542  }
543 
556  static function getICUVersion() {
557  return defined( 'INTL_ICU_VERSION' ) ? INTL_ICU_VERSION : false;
558  }
559 
567  static function getUnicodeVersionForICU() {
568  $icuVersion = IcuCollation::getICUVersion();
569  if ( !$icuVersion ) {
570  return false;
571  }
572 
573  $versionPrefix = substr( $icuVersion, 0, 3 );
574  // Source: http://site.icu-project.org/download
575  $map = array(
576  '50.' => '6.2',
577  '49.' => '6.1',
578  '4.8' => '6.0',
579  '4.6' => '6.0',
580  '4.4' => '5.2',
581  '4.2' => '5.1',
582  '4.0' => '5.1',
583  '3.8' => '5.0',
584  '3.6' => '5.0',
585  '3.4' => '4.1',
586  );
587 
588  if ( isset( $map[$versionPrefix] ) ) {
589  return $map[$versionPrefix];
590  } else {
591  return false;
592  }
593  }
594 }
595 
601 class CollationCkb extends IcuCollation {
602  function __construct() {
603  // This will set $locale and collators, which affect the actual sorting order
604  parent::__construct( 'fa' );
605  // Override the 'fa' language set by parent constructor, which affects #getFirstLetterData()
606  $this->digitTransformLanguage = Language::factory( 'ckb' );
607  }
608 }
UppercaseCollation\getFirstLetter
getFirstLetter( $string)
Given a string, return the logical "first letter" to be used for grouping on category pages and so on...
Definition: Collation.php:122
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
CollationCkb
Workaround for the lack of support of Sorani Kurdish / Central Kurdish language ('ckb') in ICU.
Definition: Collation.php:601
IcuCollation\getFirstLetterCount
getFirstLetterCount()
Definition: Collation.php:506
IcuCollation\findLowerBound
findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target)
Do a binary search, and return the index of the largest item that sorts less than or equal to the tar...
Definition: Collation.php:530
Collation\getSortKey
getSortKey( $string)
Given a string, convert it to a (hopefully short) key that can be used for efficient sorting.
UppercaseCollation
Definition: Collation.php:110
wfSuppressWarnings
wfSuppressWarnings( $end=false)
Reference-counted warning suppression.
Definition: GlobalFunctions.php:2434
IcuCollation\getPrimarySortKey
getPrimarySortKey( $string)
Definition: Collation.php:314
Collation\getFirstLetter
getFirstLetter( $string)
Given a string, return the logical "first letter" to be used for grouping on category pages and so on...
wfGetCache
wfGetCache( $inputType)
Get a cache object.
Definition: GlobalFunctions.php:4005
$wgContLang
this class mediates it Skin Encapsulates a look and feel for the wiki All of the functions that render HTML and make choices about how to render it are here and are called from various other places when and is meant to be subclassed with other skins that may override some of its functions The User object contains a reference to a and so rather than having a global skin object we just rely on the global User and get the skin with $wgUser and also has some character encoding functions and other locale stuff The current user interface language is instantiated as and the content language as $wgContLang
Definition: design.txt:56
IcuCollation\$tailoringFirstLetters
static $tailoringFirstLetters
Additional characters (or character groups) to be considered separate letters for given languages,...
Definition: Collation.php:207
Collation
Definition: Collation.php:23
Collation\singleton
static singleton()
Definition: Collation.php:29
MWException
MediaWiki exception.
Definition: MWException.php:26
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3627
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1174
wfRestoreWarnings
wfRestoreWarnings()
Restore error level to previous value.
Definition: GlobalFunctions.php:2464
IcuCollation\getSortKeyByLetterIndex
getSortKeyByLetterIndex( $index)
Definition: Collation.php:499
IcuCollation\getICUVersion
static getICUVersion()
Return the version of ICU library used by PHP's intl extension, or false when the extension is not in...
Definition: Collation.php:556
IcuCollation\isCjk
static isCjk( $codepoint)
Definition: Collation.php:535
wfRunHooks
wfRunHooks( $event, array $args=array(), $deprecatedVersion=null)
Call hook functions defined in $wgHooks.
Definition: GlobalFunctions.php:4058
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
IcuCollation\$firstLetterData
$firstLetterData
Definition: Collation.php:157
CollationCkb\__construct
__construct()
Definition: Collation.php:602
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
$value
$value
Definition: styleTest.css.php:45
UppercaseCollation\__construct
__construct()
Definition: Collation.php:112
IcuCollation\getLetterByIndex
getLetterByIndex( $index)
Definition: Collation.php:492
IcuCollation\getFirstLetter
getFirstLetter( $string)
Given a string, return the logical "first letter" to be used for grouping on category pages and so on...
Definition: Collation.php:321
CACHE_ANYTHING
const CACHE_ANYTHING
Definition: Defines.php:111
IcuCollation\getFirstLetterData
getFirstLetterData()
Definition: Collation.php:349
IdentityCollation\getSortKey
getSortKey( $string)
Given a string, convert it to a (hopefully short) key that can be used for efficient sorting.
Definition: Collation.php:138
IcuCollation\$primaryCollator
$primaryCollator
Definition: Collation.php:156
IdentityCollation\getFirstLetter
getFirstLetter( $string)
Given a string, return the logical "first letter" to be used for grouping on category pages and so on...
Definition: Collation.php:142
IdentityCollation
Collation class that's essentially a no-op.
Definition: Collation.php:136
IcuCollation\RECORD_LENGTH
const RECORD_LENGTH
Definition: Collation.php:282
IcuCollation\$mainCollator
$mainCollator
Definition: Collation.php:156
IcuCollation\FIRST_LETTER_VERSION
const FIRST_LETTER_VERSION
Definition: Collation.php:154
IcuCollation\getUnicodeVersionForICU
static getUnicodeVersionForICU()
Return the version of Unicode appropriate for the version of ICU library currently in use,...
Definition: Collation.php:567
$cache
$cache
Definition: mcc.php:32
wfGetPrecompiledData
wfGetPrecompiledData( $name)
Get an object from the precompiled serialized directory.
Definition: GlobalFunctions.php:3608
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
UppercaseCollation\$lang
$lang
Definition: Collation.php:111
utf8ToCodepoint
utf8ToCodepoint( $char)
Determine the Unicode codepoint of a single-character UTF-8 sequence.
Definition: UtfNormalUtil.php:94
IcuCollation\$locale
$locale
Definition: Collation.php:156
Collation\$instance
static $instance
Definition: Collation.php:24
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:184
ArrayUtils\findLowerBound
static findLowerBound( $valueCallback, $valueCount, $comparisonCallback, $target)
Do a binary search, and return the index of the largest item that sorts less than or equal to the tar...
Definition: ArrayUtils.php:112
IcuCollation\getSortKey
getSortKey( $string)
Given a string, convert it to a (hopefully short) key that can be used for efficient sorting.
Definition: Collation.php:304
IcuCollation\$cjkBlocks
static $cjkBlocks
Unified CJK blocks.
Definition: Collation.php:168
Collation\factory
static factory( $collationName)
Definition: Collation.php:42
IcuCollation\$digitTransformLanguage
$digitTransformLanguage
Definition: Collation.php:156
IcuCollation\__construct
__construct( $locale)
Definition: Collation.php:284
UppercaseCollation\getSortKey
getSortKey( $string)
Given a string, convert it to a (hopefully short) key that can be used for efficient sorting.
Definition: Collation.php:118
IcuCollation
Definition: Collation.php:153