static $table = array(
array( '', 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י' ),
array( '', 'י', 'כ', 'ל', 'מ', 'נ', 'ס', 'ע', 'פ', 'צ', 'ק' ),
- array( '', 'ק', 'ר', 'ש', 'ת', 'תק', 'תר', 'תש', 'תת', 'תתק', 'תתר' ),
+ array( '',
+ array( 'ק' ),
+ array( 'ר' ),
+ array( 'ש' ),
+ array( 'ת' ),
+ array( 'ת', 'ק' ),
+ array( 'ת', 'ר' ),
+ array( 'ת', 'ש' ),
+ array( 'ת', 'ת' ),
+ array( 'ת', 'ת', 'ק' ),
+ array( 'ת', 'ת', 'ר' ),
+ ),
array( '', 'א', 'ב', 'ג', 'ד', 'ה', 'ו', 'ז', 'ח', 'ט', 'י' )
);
return $num;
}
- $s = '';
+ // Round thousands have special notations
+ if ( $num === 1000 ) {
+ return "א' אלף";
+ } elseif ( $num % 1000 === 0 ) {
+ return $table[0][$num / 1000] . "' אלפים";
+ }
+
+ $letters = array();
+
for ( $pow10 = 1000, $i = 3; $i >= 0; $pow10 /= 10, $i-- ) {
if ( $num >= $pow10 ) {
- if ( $num == 15 || $num == 16 ) {
- $s .= $table[0][9] . $table[0][$num - 9];
+ if ( $num === 15 || $num === 16 ) {
+ $letters[] = $table[0][9];
+ $letters[] = $table[0][$num - 9];
$num = 0;
} else {
- $s .= $table[$i][intval( ( $num / $pow10 ) )];
- if ( $pow10 == 1000 ) {
- $s .= "'";
+ $letters = array_merge(
+ $letters,
+ (array)$table[$i][intval( $num / $pow10 )]
+ );
+
+ if ( $pow10 === 1000 ) {
+ $letters[] = "'";
}
}
}
+
$num = $num % $pow10;
}
- if ( strlen( $s ) == 2 ) {
- $str = $s . "'";
+
+ $preTransformLength = count( $letters );
+ if ( $preTransformLength === 1 ) {
+ // Add geresh (single quote) to one-letter numbers
+ $letters[] = "'";
} else {
- $str = substr( $s, 0, strlen( $s ) - 2 ) . '"';
- $str .= substr( $s, strlen( $s ) - 2, 2 );
- }
- $start = substr( $str, 0, strlen( $str ) - 2 );
- $end = substr( $str, strlen( $str ) - 2 );
- switch ( $end ) {
- case 'כ':
- $str = $start . 'ך';
- break;
- case 'מ':
- $str = $start . 'ם';
- break;
- case 'נ':
- $str = $start . 'ן';
- break;
- case 'פ':
- $str = $start . 'ף';
- break;
- case 'צ':
- $str = $start . 'ץ';
- break;
+ $lastIndex = $preTransformLength - 1;
+ $letters[$lastIndex] = str_replace(
+ array( 'כ', 'מ', 'נ', 'פ', 'צ' ),
+ array( 'ך', 'ם', 'ן', 'ף', 'ץ' ),
+ $letters[$lastIndex]
+ );
+
+ // Add gershayim (double quote) to multiple-letter numbers,
+ // but exclude numbers with only one letter after the thousands
+ // (1001-1009, 1020, 1030, 2001-2009, etc.)
+ if ( $letters[1] === "'" && $preTransformLength === 3 ) {
+ $letters[] = "'";
+ } else {
+ array_splice( $letters, -1, 0, '"' );
+ }
}
- return $str;
+
+ return implode( $letters );
}
/**
return $this->internalUserTimeAndDate( 'both', $ts, $user, $options );
}
+ /**
+ * Get the timestamp in a human-friendly relative format, e.g., "3 days ago".
+ *
+ * Determine the difference between the timestamp and the current time, and
+ * generate a readable timestamp by returning "<N> <units> ago", where the
+ * largest possible unit is used.
+ *
+ * @since 1.26 (Prior to 1.26 method existed but was not meant to be used directly)
+ *
+ * @param MWTimestamp $time
+ * @param MWTimestamp|null $relativeTo The base timestamp to compare to (defaults to now)
+ * @param User|null $user User the timestamp is being generated for (or null to use main context's user)
+ * @return string Formatted timestamp
+ */
+ public function getHumanTimestamp( MWTimestamp $time, MWTimestamp $relativeTo = null, User $user = null ) {
+ if ( $relativeTo === null ) {
+ $relativeTo = new MWTimestamp();
+ }
+ if ( $user === null ) {
+ $user = RequestContext::getMain()->getUser();
+ }
+
+ // Adjust for the user's timezone.
+ $offsetThis = $time->offsetForUser( $user );
+ $offsetRel = $relativeTo->offsetForUser( $user );
+
+ $ts = '';
+ if ( Hooks::run( 'GetHumanTimestamp', array( &$ts, $time, $relativeTo, $user, $this ) ) ) {
+ $ts = $this->getHumanTimestampInternal( $time, $relativeTo, $user );
+ }
+
+ // Reset the timezone on the objects.
+ $time->timestamp->sub( $offsetThis );
+ $relativeTo->timestamp->sub( $offsetRel );
+
+ return $ts;
+ }
+
/**
* Convert an MWTimestamp into a pretty human-readable timestamp using
* the given user preferences and relative base time.
*
- * DO NOT USE THIS FUNCTION DIRECTLY. Instead, call MWTimestamp::getHumanTimestamp
- * on your timestamp object, which will then call this function. Calling
- * this function directly will cause hooks to be skipped over.
- *
- * @see MWTimestamp::getHumanTimestamp
+ * @see Language::getHumanTimestamp
* @param MWTimestamp $ts Timestamp to prettify
* @param MWTimestamp $relativeTo Base timestamp
* @param User $user User preferences to use
* @return string Human timestamp
- * @since 1.22
+ * @since 1.26
*/
- public function getHumanTimestamp( MWTimestamp $ts, MWTimestamp $relativeTo, User $user ) {
+ private function getHumanTimestampInternal( MWTimestamp $ts, MWTimestamp $relativeTo, User $user ) {
$diff = $ts->diff( $relativeTo );
$diffDay = (bool)( (int)$ts->timestamp->format( 'w' ) -
(int)$relativeTo->timestamp->format( 'w' ) );
return false;
} else {
$fallbacks = self::getFallbacksFor( $code );
- $first = array_shift( $fallbacks );
- return $first;
+ return $fallbacks[0];
}
}
*
* @since 1.19
* @param string $code Language code
- * @return array
+ * @return array Non-empty array, ending in "en"
*/
public static function getFallbacksFor( $code ) {
if ( $code === 'en' || !Language::isValidBuiltInCode( $code ) ) {
return array();
- } else {
- $v = self::getLocalisationCache()->getItem( $code, 'fallback' );
- $v = array_map( 'trim', explode( ',', $v ) );
- if ( $v[count( $v ) - 1] !== 'en' ) {
- $v[] = 'en';
- }
- return $v;
}
+ // For unknown languages, fallbackSequence returns an empty array,
+ // hardcode fallback to 'en' in that case.
+ return self::getLocalisationCache()->getItem( $code, 'fallbackSequence' ) ?: array( 'en' );
}
/**