* @ingroup Language
*/
class FakeConverter {
-
/**
* @var Language
*/
$alpha = '[a-z]';
$digit = '[0-9]';
$alphanum = '[a-z0-9]';
- $x = 'x' ; # private use singleton
+ $x = 'x'; # private use singleton
$singleton = '[a-wy-z]'; # other singleton
$s = $lenient ? '[-_]' : '-';
throw new MWException( __METHOD__ . " must be passed a string, $type given$addmsg" );
}
- return (bool)preg_match( '/^[a-z0-9-]+$/i', $code );
+ return (bool)preg_match( '/^[a-z0-9-]{2,}$/i', $code );
}
/**
}
/**
+ * Returns an array of localised namespaces indexed by their numbers. If the namespace is not
+ * available in localised form, it will be included in English.
+ *
* @return array
*/
public function getNamespaces() {
return $this->getNsText( NS_SPECIAL ) . ':' . $name;
}
- /**
- * @return array
- */
- function getQuickbarSettings() {
- return array(
- $this->getMessage( 'qbsettings-none' ),
- $this->getMessage( 'qbsettings-fixedleft' ),
- $this->getMessage( 'qbsettings-fixedright' ),
- $this->getMessage( 'qbsettings-floatingleft' ),
- $this->getMessage( 'qbsettings-floatingright' ),
- $this->getMessage( 'qbsettings-directionality' )
- );
- }
-
/**
* @return array
*/
* internationalisation, a reduced set of format characters, and a better
* escaping format.
*
- * Supported format characters are dDjlNwzWFmMntLoYyaAgGhHiscrU. See the
- * PHP manual for definitions. There are a number of extensions, which
+ * Supported format characters are dDjlNwzWFmMntLoYyaAgGhHiscrUeIOPTZ. See
+ * the PHP manual for definitions. There are a number of extensions, which
* start with "x":
*
* xn Do not translate digits of the next numeric format character
* Backslash escaping is also supported.
*
* Input timestamp is assumed to be pre-normalized to the desired local
- * time zone, if any.
+ * time zone, if any. Note that the format characters crUeIOPTZ will assume
+ * $ts is UTC if $zone is not given.
*
* @param $format String
* @param $ts String: 14-character timestamp
* YYYYMMDDHHMMSS
* 01234567890123
+ * @param $zone DateTimeZone: Timezone of $ts
* @todo handling of "o" format character for Iranian, Hebrew, Hijri & Thai?
*
* @return string
*/
- function sprintfDate( $format, $ts ) {
+ function sprintfDate( $format, $ts, DateTimeZone $zone = null ) {
$s = '';
$raw = false;
$roman = false;
$hebrewNum = false;
- $unix = false;
+ $dateTimeObj = false;
$rawToggle = false;
$iranian = false;
$hebrew = false;
$s .= $this->getMonthNameGen( substr( $ts, 4, 2 ) );
break;
case 'xjx':
- if ( !$hebrew ) $hebrew = self::tsToHebrew( $ts );
+ if ( !$hebrew ) {
+ $hebrew = self::tsToHebrew( $ts );
+ }
$s .= $this->getHebrewCalendarMonthNameGen( $hebrew[1] );
break;
case 'd':
$num = substr( $ts, 6, 2 );
break;
case 'D':
- if ( !$unix ) $unix = wfTimestamp( TS_UNIX, $ts );
- $s .= $this->getWeekdayAbbreviation( gmdate( 'w', $unix ) + 1 );
+ if ( !$dateTimeObj ) {
+ $dateTimeObj = DateTime::createFromFormat(
+ 'YmdHis', $ts, $zone ?: new DateTimeZone( 'UTC' )
+ );
+ }
+ $s .= $this->getWeekdayAbbreviation( $dateTimeObj->format( 'w' ) + 1 );
break;
case 'j':
$num = intval( substr( $ts, 6, 2 ) );
$num = $hebrew[2];
break;
case 'l':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $s .= $this->getWeekdayName( gmdate( 'w', $unix ) + 1 );
- break;
- case 'N':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $w = gmdate( 'w', $unix );
- $num = $w ? $w : 7;
- break;
- case 'w':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $num = gmdate( 'w', $unix );
- break;
- case 'z':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
+ if ( !$dateTimeObj ) {
+ $dateTimeObj = DateTime::createFromFormat(
+ 'YmdHis', $ts, $zone ?: new DateTimeZone( 'UTC' )
+ );
}
- $num = gmdate( 'z', $unix );
- break;
- case 'W':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $num = gmdate( 'W', $unix );
+ $s .= $this->getWeekdayName( $dateTimeObj->format( 'w' ) + 1 );
break;
case 'F':
$s .= $this->getMonthName( substr( $ts, 4, 2 ) );
}
$num = $hebrew[1];
break;
- case 't':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $num = gmdate( 't', $unix );
- break;
case 'xjt':
if ( !$hebrew ) {
$hebrew = self::tsToHebrew( $ts );
}
$num = $hebrew[3];
break;
- case 'L':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $num = gmdate( 'L', $unix );
- break;
- case 'o':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $num = gmdate( 'o', $unix );
- break;
case 'Y':
$num = substr( $ts, 0, 4 );
break;
$num = substr( $ts, 12, 2 );
break;
case 'c':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
- }
- $s .= gmdate( 'c', $unix );
- break;
case 'r':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
+ case 'e':
+ case 'O':
+ case 'P':
+ case 'T':
+ // Pass through string from $dateTimeObj->format()
+ if ( !$dateTimeObj ) {
+ $dateTimeObj = DateTime::createFromFormat(
+ 'YmdHis', $ts, $zone ?: new DateTimeZone( 'UTC' )
+ );
}
- $s .= gmdate( 'r', $unix );
+ $s .= $dateTimeObj->format( $code );
break;
+ case 'w':
+ case 'N':
+ case 'z':
+ case 'W':
+ case 't':
+ case 'L':
+ case 'o':
case 'U':
- if ( !$unix ) {
- $unix = wfTimestamp( TS_UNIX, $ts );
+ case 'I':
+ case 'Z':
+ // Pass through number from $dateTimeObj->format()
+ if ( !$dateTimeObj ) {
+ $dateTimeObj = DateTime::createFromFormat(
+ 'YmdHis', $ts, $zone ?: new DateTimeZone( 'UTC' )
+ );
}
- $num = $unix;
+ $num = $dateTimeObj->format( $code );
break;
case '\\':
# Backslash escaping
private static function hebrewYearStart( $year ) {
$a = intval( ( 12 * ( $year - 1 ) + 17 ) % 19 );
$b = intval( ( $year - 1 ) % 4 );
- $m = 32.044093161144 + 1.5542417966212 * $a + $b / 4.0 - 0.0031777940220923 * ( $year - 1 );
+ $m = 32.044093161144 + 1.5542417966212 * $a + $b / 4.0 - 0.0031777940220923 * ( $year - 1 );
if ( $m < 0 ) {
$m--;
}
}
if ( strlen( $s ) == 2 ) {
$str = $s . "'";
- } else {
+ } else {
$str = substr( $s, 0, strlen( $s ) - 2 ) . '"';
$str .= substr( $s, strlen( $s ) - 2, 2 );
}
# will normalize out-of-range values so we don't have to split $minDiff
# into hours and minutes.
$t = mktime( (
- (int)substr( $ts, 8, 2 ) ), # Hours
- (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
- (int)substr( $ts, 12, 2 ), # Seconds
- (int)substr( $ts, 4, 2 ), # Month
- (int)substr( $ts, 6, 2 ), # Day
- (int)substr( $ts, 0, 4 ) ); # Year
+ (int)substr( $ts, 8, 2 ) ), # Hours
+ (int)substr( $ts, 10, 2 ) + $minDiff, # Minutes
+ (int)substr( $ts, 12, 2 ), # Seconds
+ (int)substr( $ts, 4, 2 ), # Month
+ (int)substr( $ts, 6, 2 ), # Day
+ (int)substr( $ts, 0, 4 ) ); # Year
$date = date( 'YmdHis', $t );
wfRestoreWarnings();
* @since 1.20
*/
function getDirMarkEntity( $opposite = false ) {
- if ( $opposite ) { return $this->isRTL() ? '‎' : '‏'; }
+ if ( $opposite ) {
+ return $this->isRTL() ? '‎' : '‏';
+ }
return $this->isRTL() ? '‏' : '‎';
}
function getDirMark( $opposite = false ) {
$lrm = "\xE2\x80\x8E"; # LEFT-TO-RIGHT MARK, commonly abbreviated LRM
$rlm = "\xE2\x80\x8F"; # RIGHT-TO-LEFT MARK, commonly abbreviated RLM
- if ( $opposite ) { return $this->isRTL() ? $lrm : $rlm; }
+ if ( $opposite ) {
+ return $this->isRTL() ? $lrm : $rlm;
+ }
return $this->isRTL() ? $rlm : $lrm;
}
$sign = "";
if ( intval( $number ) < 0 ) {
// For negative numbers apply the algorithm like positive number and add sign.
- $sign = "-";
+ $sign = "-";
$number = substr( $number, 1 );
}
$integerPart = array();
$numMatches = preg_match_all( "/(#+)/", $digitGroupingPattern, $matches );
preg_match( "/\d+/", $number, $integerPart );
preg_match( "/\.\d*/", $number, $decimalPart );
- $groupedNumber = ( count( $decimalPart ) > 0 ) ? $decimalPart[0]:"";
- if ( $groupedNumber === $number ) {
+ $groupedNumber = ( count( $decimalPart ) > 0 ) ? $decimalPart[0] : "";
+ if ( $groupedNumber === $number ) {
// the string does not have any number part. Eg: .12345
return $sign . $groupedNumber;
}
$start = $end = strlen( $integerPart[0] );
while ( $start > 0 ) {
- $match = $matches[0][$numMatches -1] ;
+ $match = $matches[0][$numMatches - 1];
$matchLen = strlen( $match );
$start = $end - $matchLen;
if ( $start < 0 ) {
$start = 0;
}
- $groupedNumber = substr( $number, $start, $end -$start ) . $groupedNumber ;
+ $groupedNumber = substr( $number, $start, $end -$start ) . $groupedNumber;
$end = $start;
if ( $numMatches > 1 ) {
// use the last pattern for the rest of the number
# We got the first byte only of a multibyte char; remove it.
$string = substr( $string, 0, -1 );
} elseif ( $char >= 0x80 &&
- preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
- '[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m ) )
- {
+ preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
+ '[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m )
+ ) {
# We chopped in the middle of a character; remove it
$string = $m[1];
}
break;
}
}
- if ( $pos >= $textLen ) break; // extra iteration just for above checks
+ if ( $pos >= $textLen ) {
+ break; // extra iteration just for above checks
+ }
# Read the next char...
$ch = $text[$pos];
function getGrammarForms() {
global $wgGrammarForms;
if ( isset( $wgGrammarForms[$this->getCode()] ) && is_array( $wgGrammarForms[$this->getCode()] ) ) {
- return $wgGrammarForms[$this->getCode()];
+ return $wgGrammarForms[$this->getCode()];
}
return array();
}
}
$forms = array_values( $forms );
- $pluralForm = $this->getPluralForm( $count );
+ $pluralForm = $this->getPluralRuleIndexNumber( $count );
$pluralForm = min( $pluralForm, count( $forms ) - 1 );
return $forms[$pluralForm];
}
}
}
- /**
- * Get the ordered list of fallback languages, ending with the fallback
- * language chain for the site language.
- *
- * @since 1.21
- * @param $code string Language code
- * @return array
- */
- public static function getFallbacksIncludingSiteLanguage( $code ) {
- global $wgLanguageCode;
-
- // Usually, we will only store a tiny number of fallback chains, so we
- // keep them in static memory.
- static $fallbackLanguageCache = array();
- $cacheKey = "{$code}-{$wgLanguageCode}";
-
- if ( !array_key_exists( $cacheKey, $fallbackLanguageCache ) ) {
- $fallbacks = self::getFallbacksFor( $code );
-
- // Take the final 'en' off of the array before splicing
- if ( end( $fallbacks ) === 'en' ) {
- array_pop( $fallbacks );
- }
- // Append the site's fallback chain
- $siteFallbacks = self::getFallbacksFor( $wgLanguageCode );
-
- // Eliminate any languages already included in the chain
- $siteFallbacks = array_intersect( array_diff( $siteFallbacks, $fallbacks ), $siteFallbacks );
- if ( $siteFallbacks ) {
- $fallbacks = array_merge( $fallbacks, $siteFallbacks );
- }
- if ( end( $fallbacks ) !== 'en' ) {
- $fallbacks[] = 'en';
- }
- $fallbackLanguageCache[$cacheKey] = $fallbacks;
- }
- return $fallbackLanguageCache[$cacheKey];
- }
-
/**
* Get all messages for a given language
* WARNING: this may take a long time. If you just need all message *keys*
/**
* Get the plural rules for the language
* @since 1.20
- * @return array Associative array with plural form, and plural rule as key-value pairs
+ * @return array Associative array with plural form number and plural rule as key-value pairs
*/
public function getPluralRules() {
$pluralRules = self::$dataCache->getItem( strtolower( $this->mCode ), 'pluralRules' );
}
/**
- * Find the plural form matching to the given number
- * It return the form index.
- * @return int The index of the plural form
+ * Get the plural rule types for the language
+ * @since 1.21
+ * @return array Associative array with plural form number and plural rule type as key-value pairs
+ */
+ public function getPluralRuleTypes() {
+ $pluralRuleTypes = self::$dataCache->getItem( strtolower( $this->mCode ), 'pluralRuleTypes' );
+ $fallbacks = Language::getFallbacksFor( $this->mCode );
+ if ( !$pluralRuleTypes ) {
+ foreach ( $fallbacks as $fallbackCode ) {
+ $pluralRuleTypes = self::$dataCache->getItem( strtolower( $fallbackCode ), 'pluralRuleTypes' );
+ if ( $pluralRuleTypes ) {
+ break;
+ }
+ }
+ }
+ return $pluralRuleTypes;
+ }
+
+ /**
+ * Find the index number of the plural rule appropriate for the given number
+ * @return int The index number of the plural rule
*/
- private function getPluralForm( $number ) {
+ public function getPluralRuleIndexNumber( $number ) {
$pluralRules = $this->getCompiledPluralRules();
$form = CLDRPluralRuleEvaluator::evaluateCompiled( $number, $pluralRules );
return $form;
}
+
+ /**
+ * Find the plural rule type appropriate for the given number
+ * For example, if the language is set to Arabic, getPluralType(5) should
+ * return 'few'.
+ * @since 1.21
+ * @return string The name of the plural rule type, e.g. one, two, few, many
+ */
+ public function getPluralRuleType( $number ) {
+ $index = $this->getPluralRuleIndexNumber( $number );
+ $pluralRuleTypes = $this->getPluralRuleTypes();
+ if ( isset( $pluralRuleTypes[$index] ) ) {
+ return $pluralRuleTypes[$index];
+ } else {
+ return 'other';
+ }
+ }
}