bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: printing plural values outside unsigned long int range


From: Egmont Koblinger
Subject: Re: printing plural values outside unsigned long int range
Date: Wed, 23 Aug 2006 14:42:26 +0200
User-agent: Mutt/1.5.8i

On Thu, Aug 17, 2006 at 08:01:54PM +0200, Bruno Haible wrote:

Hi,

> + In the English singular case, the number -- always 1 -- can be replaced with
> + "one":
> + 
> + @smallexample
> + printf (ngettext ("One file removed", "%d files removed", n), n);
> + @end smallexample

Please don't do so, please don't mention this in the manual! It is quite
brain-damaged, for at least two reasons:

- "One file", "2 files", "3 files" is really inconsistent and really ugly.
If "One" is written as text, then it should continue as "Two files", "Three
files" so it's time to implement a localized number-to-text converter :-)
Or if numbers are used then "1" should be a number, too.

- This approach might easily break scripts that parse the output of the
command, e.g. cut the number and use it for arithmetic processing. If the
author of the script notices that "One" is a special case, he can write ugly
workaround for it. It he doesn't notice it, his script will be buggy and it
might need intensive wide-spread usage for this bug to appear. Let's not
risk these kind of bugs to appear in front-ends and other wrapper software.


The original code in coreutils which I mentioned in
http://lists.gnu.org/archive/html/bug-coreutils/2006-08/msg00082.html
looked analogous to this one:
  printf (ngettext ("1 file removed", "%d files removed", n), n);
So "1" was also presented as a number, not as a word.

Here I requested the coreutils team and Paul agreed to change this to
printf (ngettext ("%d file removed", "%d files removed", n), n);

The result produced by the program remains the same with some negligible
performance overhead, but it helps translators create good translations.

As far as I see, translators are usually not programmers and sometimes they
don't even fully understand the logic behind ngettext. And they use software
which do not help them and create trivially bad .po files. For example
quoting from hu.po in coreutils 5.97:

  "Plural-Forms:  nplurals=1; plural=0;\n"
  "X-Generator: KBabel 1.11.1\n"
  [...]
  msgid "1 truncated record\n"
  msgid_plural "%<PRIuMAX> truncated records\n"
  msgstr[0] "1 levágott rekord\n"
  msgstr[1] "%<PRIuMAX> levágott rekord\n"

Now I just wonder why kbabel allows both "nplurals=1" and "msgstr[1]" which
clearly does not make any sense.

The translation above is clearly wrong since it always reports "1" truncated
record in Hungarian. If the English singular string is converted to use the
same format specifier, i.e.
  msgid "%<PRIuMAX> truncated record\n"
  msgid_plural "%<PRIuMAX> truncated records\n"
in this case, then translators cannot make this mistake, even if they don't
really know how ngettext works.

That's why Paul and I recommend to mention in gettext's manual to use the
same format specifier even in the singular case, e.g. "%d file removed"
instead of "1 file removed".

So, based on Paul's patch sent on 16 Aug, I recommend to apply this slightly
modified patch:

--- gettext-0.15/gettext-tools/doc/gettext.texi 2006-06-30 07:25:39.000000000 
-0700
+++ gettext-0.15-plural/gettext-tools/doc/gettext.texi  2006-08-16 
12:20:25.000000000 -0700
@@ -5198,6 +5198,18 @@ printf (ngettext ("%d file removed", "%d
 Please note that the numeric value @var{n} has to be passed to the
 @code{printf} function as well.  It is not sufficient to pass it only to
 @code{ngettext}.
+
+When translating format strings, it is usually better to use the same
+conversion specifications, and use wordings as similar as possible in
address@hidden and @var{msgid2}, as this simplifies the translator's job.
+For example:
+
address@hidden
+/* Avoid usages like this one.  */
+printf (ngettext ("1 file removed", "%d files removed", n), n);
+/* Use this one instead.  */
+printf (ngettext ("%d file removed", "%d files removed", n), n);
address@hidden smallexample
 @end deftypefun
 
 @deftypefun {char *} dngettext (const char address@hidden, const char 
address@hidden, const char address@hidden, unsigned long int @var{n})



-- 
Egmont




reply via email to

[Prev in Thread] Current Thread [Next in Thread]