Counts for singulars in DateFormatter::formatInterval() are hardcoded to 1

Created on 24 April 2016, over 8 years ago
Updated 18 September 2023, about 1 year ago

Problem/Motivation

Function format_interval() in the file: includes/common.inc returns in some cases wrong value "1" instead of correct value of given interval.

For example:
1 min 1 sek instead of 31 min 21 sec.

The $units variable is array with keyed singular|plural.

$units = array(
    '1 year|@count years' => 31536000,
    '1 month|@count months' => 2592000,
    '1 week|@count weeks' => 604800,
    '1 day|@count days' => 86400,
    '1 hour|@count hours' => 3600,
    '1 min|@count min' => 60,
    '1 sec|@count sec' => 1
  );

These keys are used as parameters in function format_plural(). This function calls locale_get_plural() function, if exists. Function locale_get_plural() returns plural form index for a specific number. The index is computed from the formula of given language. In short, it returns 0 if number is singular.

Some languages (f.e. Czech - langcode "cs") use singulars for numbers ending with number 1 (f.e. 21, 31.. 91, 101 etc.). That's why locale_get_plural() returns 0 = singular.

Czech language plural formula snippet ($language->formula):

if ((((n % 10) == 1) && ((n % 100) != 11))) {
    $plural = ((0));
}

The problem is that all singulars in format_interval() are hardcoded to 1, so function returns 1 instead of 21. This function is used in Views for "Time ago" formater, so all views with time ago formater for Czech language display wrong values.

Step to reproduce

  • Locale module must be enabled.
  • Add Czech language at admin/config/regional/language

Use this simple test:

$time_diffs = array(21, 31, 41, 51, 81);
  foreach ($time_diffs as $time_diff) {
    $timeago1 = format_interval($time_diff, 2, 'cs');
    $timeago2 = format_interval($time_diff, 2, 'en');
    print $time_diff . ' sec. = ' . $timeago1 . ', should be ' . $timeago2;
    print '<br>';
  }

Results:

21 sec. = 1 sek, should be 21 sec
31 sec. = 1 sek, should be 31 sec
41 sec. = 1 sek, should be 41 sec
51 sec. = 1 sek, should be 51 sec
81 sec. = 1 min 1 sek, should be 1 min 21 sec

Proposed resolution

The $units key for singular could contain @count instead of "1".

$units = array(
    '@count year|@count years' => 31536000,
    '@count month|@count months' => 2592000,
    '@count week|@count weeks' => 604800,
    '@count day|@count days' => 86400,
    '@count hour|@count hours' => 3600,
    '@count min|@count min' => 60,
    '@count sec|@count sec' => 1
  );

Tested for test code above and works well.

🐛 Bug report
Status

Fixed

Version

11.0 🔥

Component
Language system 

Last updated about 11 hours ago

  • Maintained by
  • 🇩🇪Germany @sun
Created by

🇨🇿Czech Republic martin_klima

Live updates comments and jobs are added and updated live.
  • Needs backport to D7

    After being applied to the 8.x branch, it should be considered for backport to the 7.x branch. Note: This tag should generally remain even after the backport has been written, approved, and committed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024