From e5a9b38294da994f41ac568a16cd5cf4f0bdaf36 Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Fri, 23 Sep 2011 22:17:10 +0000 Subject: [PATCH] Make Language::formatTimePeriod() more flexible so it can produce stuff like '3 hours ago'. * Add a $noAbbrevs parameter that causes the 'seconds', 'minutes', etc. messages to be used instead of the 'seconds-abbrev', 'minutes-abbrev', etc. messages * Add the 'seconds', 'minutes', 'hours' and 'days' messages * Change the -abbrev messages to take a parameter rather than having the number prepended to them. This is for compatibility with 'seconds' et al, which need the parameter for {{PLURAL:}}. It also generally makes more sense. This does BREAK the messages in non-English languages that override them; Niklas told me to leave this alone and ping the TranslateWiki folks * Introduce an 'ago' message for '$1 ago'. Not currently used in core, but I want to use it in an extension and it seemed stupid not to have such a thing in core. * Refactor the function to use message objects and pass the number as a parameter * Add tests! They exposed a subtle bug in my first iteration; all hail tests! --- languages/Language.php | 36 +++++++++-------- languages/messages/MessagesEn.php | 13 +++++-- tests/phpunit/languages/LanguageTest.php | 49 ++++++++++++++++-------- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/languages/Language.php b/languages/Language.php index 6faf7e6ef5..b2ad81915e 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -3552,15 +3552,20 @@ class Language { * @param $format String Optional, one of ("avoidseconds","avoidminutes"): * "avoidseconds" - don't mention seconds if $seconds >= 1 hour * "avoidminutes" - don't mention seconds/minutes if $seconds > 48 hours + * @param $noAbbrevs Bool If true (or true-ish, recommend using 'noabbrevs' for clarity), use 'seconds' and friends instead of 'seconds-abbrev' and friends * @return string */ - function formatTimePeriod( $seconds, $format = false ) { + function formatTimePeriod( $seconds, $format = false, $noAbbrevs = false ) { + $secondsMsg = wfMessage( $noAbbrevs ? 'seconds' : 'seconds-abbrev' )->inLanguage( $this ); + $minutesMsg = wfMessage( $noAbbrevs ? 'minutes' : 'minutes-abbrev' )->inLanguage( $this ); + $hoursMsg = wfMessage( $noAbbrevs ? 'hours' : 'hours-abbrev' )->inLanguage( $this ); + $daysMsg = wfMessage( $noAbbrevs ? 'days' : 'days-abbrev' )->inLanguage( $this ); if ( round( $seconds * 10 ) < 100 ) { $s = $this->formatNum( sprintf( "%.1f", round( $seconds * 10 ) / 10 ) ); - $s .= $this->getMessageFromDB( 'seconds-abbrev' ); + $s = $secondsMsg->params( $s )->text(); } elseif ( round( $seconds ) < 60 ) { $s = $this->formatNum( round( $seconds ) ); - $s .= $this->getMessageFromDB( 'seconds-abbrev' ); + $s = $secondsMsg->params( $s )->text(); } elseif ( round( $seconds ) < 3600 ) { $minutes = floor( $seconds / 60 ); $secondsPart = round( fmod( $seconds, 60 ) ); @@ -3568,9 +3573,9 @@ class Language { $secondsPart = 0; $minutes++; } - $s = $this->formatNum( $minutes ) . $this->getMessageFromDB( 'minutes-abbrev' ); + $s = $minutesMsg->params( $this->formatNum( $minutes ) )->text(); $s .= ' '; - $s .= $this->formatNum( $secondsPart ) . $this->getMessageFromDB( 'seconds-abbrev' ); + $s .= $secondsMsg->params( $this->formatNum( $secondsPart ) )->text(); } elseif ( round( $seconds ) <= 2 * 86400 ) { $hours = floor( $seconds / 3600 ); $minutes = floor( ( $seconds - $hours * 3600 ) / 60 ); @@ -3583,12 +3588,11 @@ class Language { $minutes = 0; $hours++; } - $s = $this->formatNum( $hours ) . $this->getMessageFromDB( 'hours-abbrev' ); + $s = $hoursMsg->params( $this->formatNum( $hours ) )->text(); $s .= ' '; - $s .= $this->formatNum( $minutes ) . $this->getMessageFromDB( 'minutes-abbrev' ); + $s .= $minutesMsg->params( $this->formatNum( $minutes ) )->text(); if ( !in_array( $format, array( 'avoidseconds', 'avoidminutes' ) ) ) { - $s .= ' ' . $this->formatNum( $secondsPart ) . - $this->getMessageFromDB( 'seconds-abbrev' ); + $s .= ' ' . $secondsMsg->params( $this->formatNum( $secondsPart ) )->text(); } } else { $days = floor( $seconds / 86400 ); @@ -3598,9 +3602,9 @@ class Language { $hours = 0; $days++; } - $s = $this->formatNum( $days ) . $this->getMessageFromDB( 'days-abbrev' ); + $s = $daysMsg->params( $this->formatNum( $days ) )->text(); $s .= ' '; - $s .= $this->formatNum( $hours ) . $this->getMessageFromDB( 'hours-abbrev' ); + $s .= $hoursMsg->params( $this->formatNum( $hours ) )->text(); } elseif ( $format === 'avoidseconds' ) { $hours = floor( ( $seconds - $days * 86400 ) / 3600 ); $minutes = round( ( $seconds - $days * 86400 - $hours * 3600 ) / 60 ); @@ -3612,15 +3616,15 @@ class Language { $hours = 0; $days++; } - $s = $this->formatNum( $days ) . $this->getMessageFromDB( 'days-abbrev' ); + $s = $daysMsg->params( $this->formatNum( $days ) )->text(); $s .= ' '; - $s .= $this->formatNum( $hours ) . $this->getMessageFromDB( 'hours-abbrev' ); + $s .= $hoursMsg->params( $this->formatNum( $hours ) )->text(); $s .= ' '; - $s .= $this->formatNum( $minutes ) . $this->getMessageFromDB( 'minutes-abbrev' ); + $s .= $minutesMsg->params( $this->formatNum( $minutes ) )->text(); } else { - $s = $this->formatNum( $days ) . $this->getMessageFromDB( 'days-abbrev' ); + $s = $daysMsg->params( $this->formatNum( $days ) )->text(); $s .= ' '; - $s .= $this->formatTimePeriod( $seconds - $days * 86400, $format ); + $s .= $this->formatTimePeriod( $seconds - $days * 86400, $format, $noAbbrevs ); } } return $s; diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 6282357e66..5161dd834b 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -3656,10 +3656,15 @@ By executing it, your system may be compromised.", # Video information, used by Language::formatTimePeriod() to format lengths in the above messages 'video-dims' => '$1, $2×$3', # only translate this message to other languages if you have to change it -'seconds-abbrev' => 's', # only translate this message to other languages if you have to change it -'minutes-abbrev' => 'm', # only translate this message to other languages if you have to change it -'hours-abbrev' => 'h', # only translate this message to other languages if you have to change it -'days-abbrev' => 'd', # only translate this message to other languages if you have to change it +'seconds-abbrev' => '$1s', # only translate this message to other languages if you have to change it +'minutes-abbrev' => '$1m', # only translate this message to other languages if you have to change it +'hours-abbrev' => '$1h', # only translate this message to other languages if you have to change it +'days-abbrev' => '$1d', # only translate this message to other languages if you have to change it +'seconds' => '{{PLURAL:$1|$1 second|$1 seconds}}', +'minutes' => '{{PLURAL:$1|$1 minute|$1 minutes}}', +'hours' => '{{PLURAL:$1|$1 hour|$1 hours}}', +'days' => '{{PLURAL:$1|$1 day|$1 days}}', +'ago' => '$1 ago', # Bad image list 'bad_image_list' => 'The format is as follows: diff --git a/tests/phpunit/languages/LanguageTest.php b/tests/phpunit/languages/LanguageTest.php index d2b87b048b..a0272847af 100644 --- a/tests/phpunit/languages/LanguageTest.php +++ b/tests/phpunit/languages/LanguageTest.php @@ -21,27 +21,42 @@ class LanguageTest extends MediaWikiTestCase { } /** @dataProvider provideFormattableTimes */ - function testFormatTimePeriod( $seconds, $avoid, $expected, $desc ) { - $this->assertEquals( $expected, $this->lang->formatTimePeriod( $seconds, $avoid ), $desc ); + function testFormatTimePeriod( $seconds, $avoid, $noAbbrevs, $expected, $desc ) { + $this->assertEquals( $expected, $this->lang->formatTimePeriod( $seconds, $avoid, $noAbbrevs ), $desc ); } function provideFormattableTimes() { return array( - array( 9.45, false, '9.5s', 'formatTimePeriod() rounding (<10s)' ), - array( 9.95, false, '10s', 'formatTimePeriod() rounding (<10s)' ), - array( 59.55, false, '1m 0s', 'formatTimePeriod() rounding (<60s)' ), - array( 119.55, false, '2m 0s', 'formatTimePeriod() rounding (<1h)' ), - array( 3599.55, false, '1h 0m 0s', 'formatTimePeriod() rounding (<1h)' ), - array( 7199.55, false, '2h 0m 0s', 'formatTimePeriod() rounding (>=1h)' ), - array( 7199.55, 'avoidseconds', '2h 0m', 'formatTimePeriod() rounding (>=1h), avoidseconds' ), - array( 7199.55, 'avoidminutes', '2h 0m', 'formatTimePeriod() rounding (>=1h), avoidminutes' ), - array( 172799.55, 'avoidseconds', '48h 0m', 'formatTimePeriod() rounding (=48h), avoidseconds' ), - array( 259199.55, 'avoidminutes', '3d 0h', 'formatTimePeriod() rounding (>48h), avoidminutes' ), - array( 176399.55, 'avoidseconds', '2d 1h 0m', 'formatTimePeriod() rounding (>48h), avoidseconds' ), - array( 176399.55, 'avoidminutes', '2d 1h', 'formatTimePeriod() rounding (>48h), avoidminutes' ), - array( 259199.55, 'avoidseconds', '3d 0h 0m', 'formatTimePeriod() rounding (>48h), avoidseconds' ), - array( 172801.55, 'avoidseconds', '2d 0h 0m', 'formatTimePeriod() rounding, (>48h), avoidseconds' ), - array( 176460.55, false, '2d 1h 1m 1s', 'formatTimePeriod() rounding, recursion, (>48h)' ), + array( 9.45, false, false, '9.5s', 'formatTimePeriod() rounding (<10s)' ), + array( 9.45, false, 'noabbrevs', '9.5 seconds', 'formatTimePeriod() rounding (<10s)' ), + array( 9.95, false, false, '10s', 'formatTimePeriod() rounding (<10s)' ), + array( 9.95, false, 'noabbrevs', '10 seconds', 'formatTimePeriod() rounding (<10s)' ), + array( 59.55, false, false, '1m 0s', 'formatTimePeriod() rounding (<60s)' ), + array( 59.55, false, 'noabbrevs', '1 minute 0 seconds', 'formatTimePeriod() rounding (<60s)' ), + array( 119.55, false, false, '2m 0s', 'formatTimePeriod() rounding (<1h)' ), + array( 119.55, false, 'noabbrevs', '2 minutes 0 seconds', 'formatTimePeriod() rounding (<1h)' ), + array( 3599.55, false, false, '1h 0m 0s', 'formatTimePeriod() rounding (<1h)' ), + array( 3599.55, false, 'noabbrevs', '1 hour 0 minutes 0 seconds', 'formatTimePeriod() rounding (<1h)' ), + array( 7199.55, false, false, '2h 0m 0s', 'formatTimePeriod() rounding (>=1h)' ), + array( 7199.55, false, 'noabbrevs', '2 hours 0 minutes 0 seconds', 'formatTimePeriod() rounding (>=1h)' ), + array( 7199.55, 'avoidseconds', false, '2h 0m', 'formatTimePeriod() rounding (>=1h), avoidseconds' ), + array( 7199.55, 'avoidseconds', 'noabbrevs', '2 hours 0 minutes', 'formatTimePeriod() rounding (>=1h), avoidseconds' ), + array( 7199.55, 'avoidminutes', false, '2h 0m', 'formatTimePeriod() rounding (>=1h), avoidminutes' ), + array( 7199.55, 'avoidminutes', 'noabbrevs', '2 hours 0 minutes', 'formatTimePeriod() rounding (>=1h), avoidminutes' ), + array( 172799.55, 'avoidseconds', false, '48h 0m', 'formatTimePeriod() rounding (=48h), avoidseconds' ), + array( 172799.55, 'avoidseconds', 'noabbrevs', '48 hours 0 minutes', 'formatTimePeriod() rounding (=48h), avoidseconds' ), + array( 259199.55, 'avoidminutes', false, '3d 0h', 'formatTimePeriod() rounding (>48h), avoidminutes' ), + array( 259199.55, 'avoidminutes', 'noabbrevs', '3 days 0 hours', 'formatTimePeriod() rounding (>48h), avoidminutes' ), + array( 176399.55, 'avoidseconds', false, '2d 1h 0m', 'formatTimePeriod() rounding (>48h), avoidseconds' ), + array( 176399.55, 'avoidseconds', 'noabbrevs', '2 days 1 hour 0 minutes', 'formatTimePeriod() rounding (>48h), avoidseconds' ), + array( 176399.55, 'avoidminutes', false, '2d 1h', 'formatTimePeriod() rounding (>48h), avoidminutes' ), + array( 176399.55, 'avoidminutes', 'noabbrevs', '2 days 1 hour', 'formatTimePeriod() rounding (>48h), avoidminutes' ), + array( 259199.55, 'avoidseconds', false, '3d 0h 0m', 'formatTimePeriod() rounding (>48h), avoidseconds' ), + array( 259199.55, 'avoidseconds', 'noabbrevs', '3 days 0 hours 0 minutes', 'formatTimePeriod() rounding (>48h), avoidseconds' ), + array( 172801.55, 'avoidseconds', false, '2d 0h 0m', 'formatTimePeriod() rounding, (>48h), avoidseconds' ), + array( 172801.55, 'avoidseconds', 'noabbrevs', '2 days 0 hours 0 minutes', 'formatTimePeriod() rounding, (>48h), avoidseconds' ), + array( 176460.55, false, false, '2d 1h 1m 1s', 'formatTimePeriod() rounding, recursion, (>48h)' ), + array( 176460.55, false, 'noabbrevs', '2 days 1 hour 1 minute 1 second', 'formatTimePeriod() rounding, recursion, (>48h)' ), ); } -- 2.20.1