Subject: bug#26621: hint for translators is missing from POT file, but is opaque anyhow

From: Paul Eggert <[email-masked]>
Date: Mon, 24 Apr 2017 00:38:07 -0700

Benno Schulenberg wrote:
> Fourth, the first part of the comment begins with this:
>
>      The instances of "s" in the following formats are
>      the SI symbol "s" (meaning second), and should not be translated.
>
> Why should they not be translated?  In order to avoid problems
> with grammatical congruence in languages like Polish?

Yes. This is part of the SI standard. SI abbreviations are supposed to be 
identical in all languages, regardless of grammar issues.

> It would be nicer to use a fixed number of
> decimals so that the message doesn't unnecessarily "jump".

Yes, and since the messages you're talking about are supposed to come out once a 
second, dd should just omit everything after the decimal point.

> Sixth, the format string uses %g, which means that the
> number of seconds will be displayed in exponential form
> when the number becomes very large.  Is that intentional?

Yes, it's been that way since that code was introduced in 2004 (before 
status=progress was added). The idea I had back then was that we want more than 
1 digit when transfer times are short, and that we needn't bother with lots of 
digits when transfer times are long. I've never heard of a real-world situation 
where the exponential notation actually gets used (more than 11 days for the 
transfer, if I calculate aright) so the issue is to some extent academic.

Thanks for your other comments. I installed the attached patch, which I hope 
addresses them.
From fa9510a8bba71fc468694ae81ccdfe45bc1814e3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Mon, 24 Apr 2017 00:06:00 -0700
Subject: [PATCH] dd: status=progress outputs "6 s", not "6.00001 s"

Problem reported by Benno Schulenberg (Bug#26621).
* NEWS: Document this.
* src/dd.c (print_xfer_stats): With status=progress,
format times with %.0f rather than %g.  Improve
translator comments.
---
 NEWS     |  4 ++++
 src/dd.c | 47 +++++++++++++++++++++++++++++++++--------------
 2 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/NEWS b/NEWS
index 07cb283..72981b6 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,10 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Bug fixes
 
+  dd status=progress now just counts seconds; e.g., it outputs "6 s"
+  consistently rather than sometimes outputting "6.00001 s".
+  [bug introduced in coreutils-8.24]
+
   df non longer interacts with excluded file system types, so for example
   specifying -x nfs will no longer hang with problematic nfs mounts.
   [bug introduced in coreutils-8.21]
diff --git a/src/dd.c b/src/dd.c
index 8ab1efa..119f307 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -795,29 +795,48 @@ print_xfer_stats (xtime_t progress_time)
   if (progress_time)
     fputc ('\r', stderr);
 
-  /* TRANSLATORS: The instances of "s" in the following formats are
-     the SI symbol "s" (meaning second), and should not be translated.
+  /* Use full seconds when printing progress, since the progress
+     report is output once per second and there is little point
+     displaying any subsecond jitter.  Use default precision with %g
+     otherwise, as this provides more-useful output then.  With long
+     transfers %g can generate a number with an exponent; that is OK.  */
+  char delta_s_buf[20];
+  snprintf (delta_s_buf, sizeof delta_s_buf,
+            progress_time ? "%.0f" : "%g", delta_s);
+
+  /* TRANSLATORS: Because SI symbols should be the same in all
+     languages, the instances of "s" in the following formats, which
+     are the SI symbol "s" (meaning second), should not be translated.
      The strings use SI symbols for better internationalization even
-     though they may be a bit more confusing in English.  If one of
-     these formats A looks shorter on the screen than another format
-     B, then A's string length should be less than B's, and appending
-     strlen (B) - strlen (A) spaces to A should make it appear to be
-     at least as long as B.  */
+     though they may be a bit more confusing in English.
+
+     These strings should be translated so that a new output line B
+     completely overwrites an old line A that is already present on
+     the screen, if (sB < sA ? sA - sB : 0) spaces are appended to B,
+     where sA == strlen (A) and sB == strlen (B).  For example, in a
+     UTF-8 locale where A is "8 bajtů zkopírováno, 1 s, 0 kB/s" (32
+     columns, strlen 35) and B is "19979567104 bajtů (20 GB, 19 GiB)
+     zkopírováno, 2 s, 10.0 GB/s" (61 columns, strlen 64), the
+     translation is OK because A looks shorter than B (32 vs 61
+     columns) even when no spaces are appended.  */
 
   int stats_len
     = (abbreviation_lacks_prefix (si)
        ? fprintf (stderr,
-                  ngettext ("%"PRIuMAX" byte copied, %g s, %s/s",
-                            "%"PRIuMAX" bytes copied, %g s, %s/s",
+                  /* TRANSLATORS: See comments in dd.c's print_xfer_stats.  */
+                  ngettext ("%"PRIuMAX" byte copied, %s s, %s/s",
+                            "%"PRIuMAX" bytes copied, %s s, %s/s",
                             select_plural (w_bytes)),
-                  w_bytes, delta_s, bytes_per_second)
+                  w_bytes, delta_s_buf, bytes_per_second)
        : abbreviation_lacks_prefix (iec)
        ? fprintf (stderr,
-                  _("%"PRIuMAX" bytes (%s) copied, %g s, %s/s"),
-                  w_bytes, si, delta_s, bytes_per_second)
+                  /* TRANSLATORS: See comments in dd.c's print_xfer_stats.  */
+                  _("%"PRIuMAX" bytes (%s) copied, %s s, %s/s"),
+                  w_bytes, si, delta_s_buf, bytes_per_second)
        : fprintf (stderr,
-                  _("%"PRIuMAX" bytes (%s, %s) copied, %g s, %s/s"),
-                  w_bytes, si, iec, delta_s, bytes_per_second));
+                  /* TRANSLATORS: See comments in dd.c's print_xfer_stats.  */
+                  _("%"PRIuMAX" bytes (%s, %s) copied, %s s, %s/s"),
+                  w_bytes, si, iec, delta_s_buf, bytes_per_second));
 
   if (progress_time)
     {
-- 
2.7.4