After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 149586 - String composition is bad in battstat applet
String composition is bad in battstat applet
Status: RESOLVED FIXED
Product: gnome-applets
Classification: Other
Component: battery
git master
Other All
: High normal
: ---
Assigned To: gnome-applets Maintainers
gnome-applets Maintainers
Depends on:
Blocks: 150905
 
 
Reported: 2004-08-07 19:41 UTC by Danilo Segan
Modified: 2004-12-22 21:47 UTC
See Also:
GNOME target: ---
GNOME version: 2.7/2.8


Attachments
Fix strings in battery status applets for L10N (10.21 KB, patch)
2004-08-08 10:49 UTC, Danilo Segan
none Details | Review
fix for this problem and more (13.67 KB, patch)
2004-08-08 14:38 UTC, Danielle Madeley
none Details | Review
better fix, perhaps? (14.28 KB, patch)
2004-08-09 02:54 UTC, Danielle Madeley
none Details | Review
more cleanups (16.39 KB, patch)
2004-08-09 09:03 UTC, Danielle Madeley
none Details | Review

Description Danilo Segan 2004-08-07 19:41:43 UTC
String composition like below is VERY WRONG.  One simply cannot translate this
appropriately.

#. Translation Note: as in "No time remaining" or "No time till charged"
#: battstat/battstat_applet.c:365
msgid "No time"

#. Translation Note: as in "Unknown time remaining" or "Unknown time till charged"
#. Translation Note: as in "Unknown time remaining"
#: battstat/battstat_applet.c:368 battstat/battstat_applet.c:1145
msgid "Unknown time"


This seems to be used in places like:

#: battstat/battstat_applet.c:818 battstat/battstat_applet.c:1197
#, c-format
msgid "System is running on AC power. %s (%d%%) till charged."

You should probably have these in separate messages:
"Unknown time (%d%%) till charged."
"No time (%d%%) till charged."
"%s (%d%%) till charged."
"Unknown time (%d%%) remaining."
"No time (%d%%) remaining."
"%s (%d%%) remaining."

Otherwise, there's no chance to translate this in some languages without getting
obscure sentenses.
Comment 1 Danielle Madeley 2004-08-08 02:45:13 UTC
Mmm, I appreciate why this sucks. I want to try and fix it, at the moment I feel
there are too many almost identical strings in the applet anyway. The problem
is, this is probably going to require some structural changes, I'll try and get
it done before the string freeze.
Comment 2 Danilo Segan 2004-08-08 10:49:13 UTC
Created attachment 30329 [details] [review]
Fix strings in battery status applets for L10N

How about this patch?  Untested, and would require a bit of cleaning up the
comments.

2004-08-08  Danilo Šegan  <dsegan@gmx.net>

	Fix bug #149586.
	
	* battstat_applet.c (get_remaining): Add batstatus and remaining
	parameters.
	(pixmap_timeout, change_orient): Adjust calls to get_remaining().
Comment 3 Danilo Segan 2004-08-08 10:58:04 UTC
Just a note.  Even my solution would cause problems in handling plural forms for
some languages.

For instance, "remaining" (in Serbian) should have a different form if we have
"21 hours" and another form if we have "4 hours".  I can get around this using a
form which is uncommon for modern-Serbian, but it would still be better if we
had something like:

/* %s is replaced with something like "%d minutes" */
g_strdup_printf( ngettext("%d hour %s (%d%%) remaining", "%d hours %s
remaining", hour), hour, min_string, batstatus );

But, I'm not sure if it would work fine for all languages (i.e. in some
languages form of "remaining" may depend on the number of minutes, instead of
number of hours as in Serbian).

Of course, all of this applies equally to "till charged" constructs.
Comment 4 Danilo Segan 2004-08-08 11:01:12 UTC
Another note about the patch: those strings with "\n" at the end should probably
be changed slightly: remove \n from them, and add ,"\n" after _() call (inside
g_strconcat call), so they would get reused (there're already exactly the same
strings elsewhere in the code).
Comment 5 Danielle Madeley 2004-08-08 14:32:12 UTC
I had a bit of a brain wave about this. Rather then adding things to parse to
the get_remaining () call, you may as well pass the entire struct. This way the
call can pass back a much more intelligent string. This allows us to deal with a
lot of edge cases where we want to say certain things.

I've also added global strings to deal with commonly appearing strings meaning
you should only need to translate them once.

I'm not sure how to deal with your problem of having to use different counters
depending on the size of the number. How do others resolve this?
Comment 6 Danielle Madeley 2004-08-08 14:38:58 UTC
Created attachment 30333 [details] [review]
fix for this problem and more

Here is the patch I just mentioned. Are there any obvious translation issues
here? I'm going to mail this to gnome-i18n to see if they can see any issues.
Comment 7 Danilo Segan 2004-08-08 23:52:56 UTC
Ok, so you basically went the route I went above with my patch, just a bit more
cleanly ;-)

A couple of notes.

First of all, I'm not so sure about the following.  You're probably avoiding _()
here because it returns a pointer to static storage, but you seem to be
forgetting to put ac_power_string and dc_power_string inside gettext() call, so
these will probably end up untranslated (even though translators translate will
them).

+char *ac_power_string = N_("System is running on AC power");
+char *dc_power_string = N_("System is running on battery power");
...
+		new_label = g_strdup_printf ("%s\n%s",
+				ac_power_string,
+				new_string);
...
+		new_label = g_strdup (dc_power_string);

You should put these as gettext(ac_power_string) and gettext(dc_power_string) --
there're more of these.


Now, since you're already doing some checks in the code, I guess it would be
nice to put entire sentences into ngettext calls:

 		if (hours == 0)
 		{
+			char *return_string;
+			return_string = g_strdup_printf (_("%s (%d%%) remaining"),
+					mins_string, batt_life);

This should rather be:
 		if (hours == 0)
 		{
+			char *return_string;
+			return_string = g_strdup_printf (ngettext("%d minute (%d%%) remaining", "%d
minutes (%d%%) remaining", mins),
+					mins, batt_life);

This is useful because in some languages form of the "remaining" also depends on
the number.  This also applies to the mins==0 case.

Of course, it would be nice if one could easily solve this for hours!=0 and
mins!=0 as well, but I don't know if what would work for Serbian would work for
other languages.  We'd need input from other translators (if it doesn't break it
for them, I'd be more than happy to have this as well, since I'd be able to
provide perfect Serbian translations ;-).

I.e. for Serbian it would be:
 printf(ngettext("%d hour %s remaining", "%d hours %s remaining", hours), hours,
minsstring)
while for some other languages it might be
 printf(ngettext("%s %d minute remaining", "%s %d minutes remaining", mins),
hoursstring, mins)
Comment 8 Danilo Segan 2004-08-09 00:07:25 UTC
Another comment on:
> I've also added global strings to deal with commonly appearing strings meaning
> you should only need to translate them once.

There's no need to do it this way.  Gettext merges all messages which are the
same (thus the above [after my patch] talk about separating \n and . from the
messages).  This means that if you have in the code something like:
  bla1 = g_strdup(_("This is great"));
  bla2 = g_strdup_printf("%s\n", _("This is great"));
translators would have to translate "This is great" only once (that's gettext
feature; or misfeature, when you need to differentiate messages on the context
:).  No need to hack around with putting this in a variable first, etc.
Comment 9 Danielle Madeley 2004-08-09 02:54:10 UTC
Created attachment 30353 [details] [review]
better fix, perhaps?

Ok, I've moved the ngettext calls into the returns to remove the amount of
string composition. I wasn't sure how to do it for the double plural sentance,
so I've done it the way I think it should be done.

I've also moved the N_() calls which you said are wrong to #defines, which I
suspect are wrong. Basically, I don't want to have to look at the same string
over and over ;) If #defines don't work, I'll use a static inline or something
(or just give up and put them back in).

Comments appriciated as soon as possible. Thanks.
Comment 10 Danielle Madeley 2004-08-09 09:03:36 UTC
Created attachment 30359 [details] [review]
more cleanups

Cleanups, this is what I intend to commit unless someone noticed any more
issues before this evening.
Comment 11 Danilo Segan 2004-08-09 09:15:40 UTC
Davyd, everything looks fine from my perspective, and I guess everyone can
translate it as good as it's possible now.  Thanks for investing so much time in
this.
Comment 12 Danielle Madeley 2004-08-09 09:22:14 UTC
Excellent. This is committed then. Thanks for your help.
Comment 13 Raphael Higino 2004-08-12 18:15:33 UTC
There is a new problem now. In the string below:

#. TRANSLATOR: "%d %s %d %s" are "%d hours %d minutes"
#. * Swap order with "%2$s %2$d %1$s %1$d if needed
#: battstat/battstat_applet.c:414
#, c-format
msgid "%d %s %d %s (%d%%) remaining"

the word "remaining", in some languages, may be translated in plural or
singular depending on the time remaining. It will be wrong in these
languages if there's no support for plurals on it.

I don't know how this problem could be properly solved (maybe using
ngettext), but I wouldn't like to have reverse word order to translate
this string. It would look like "Tempo restante: %d %s %d %s (%d%%)"
(or in English "Time remaining: %d %s %d %s (%d%%)") which is not so
natural and would break the way the status messages were going up to now.
Comment 14 Danilo Segan 2004-08-12 19:15:01 UTC
Raphael, it's the problem I mention above.

It cannot be solved without knowing on *what* to pluralize. For Serbian, we'd
need to pluralize on hours, but in the message "%d %s %d %s (%d%%) till
charged", we'd need it to be pluralized on minutes (that's because word
"remaining" would go in front of the time, and "till charged" after it in
Serbian translation).

So, do you have any magic solution that would work for both cases?
Comment 15 Danielle Madeley 2004-08-12 23:31:48 UTC
I don't think you can use ngettext for to independantly pluralize two numbers.
Would it help if 'remaining' was put into an ngettext of it's own? Making it
something like:
    g_strdup_printf (_("%d %s %d %s (%d%%) %s"),
        /* strings */
        ngettext (remaining, remaining, hours + mins));

Other then that, I'm not sure what to do. This is a hard problem, and a possible
limitation of ngettext (although how would you solve it?)
Comment 16 Danilo Segan 2004-08-13 00:44:44 UTC
Davyd, that wouldn't help (especially not with it being pluralized on such crap
value such as sum of hours and minutes ;-).

What might help is doing something like the following.

/* Translators: translate this to either "hours" or "mins". "%d %s %d %s
remaining" message below will be pluralized on the value you select here. */
char *choice = g_strdup(_("mins"));

if (strcmp(choice, "mins")) {
   remstring = g_strdup(ngettext("%d %s %d %s remaining", "%d %s %d %s
remaining", hours));
} else {
   remstring = g_strdup(ngettext("%d %s %d %s remaining", "%d %s %d %s
remaining", mins));
}

Then, passing remstring in g_strdup_printf call.

This is very hackish, though I believe it will solve the problem for all
translators.  It's even worse than "hackish", because one would have to provide
the same hack for "%d %s %d %s till charged" message, and since "mins" is
already used (remember, gettext provides ability to translate this message only
once), we'd need to perhaps use "hours" there as a default keyword, and invert
the if logic.  Of course, you can perhaps use completely different keywords,
such as "pluralize-remaining-on: mins" and "pluralize-till-charged-on: mins",
remembering to adjust translators' comment and strcmp compare.

Because of this foo-for-the-bar nature of the solution (letting translator
handle which number should it be pluralized on, since it can be pluralized only
on the one), I'm not pushing too hard for it, and I rarely mention it anywhere
as a real option to consider.

But, it's up to you Davyd, and up to other translators to weight merits and
disadvantages of the method.
Comment 17 Danielle Madeley 2004-08-15 14:16:15 UTC
I haven't had time to look into this bug. It doesn't look like I'll have time to
fix it before the release tomorrow. At least it will give me time to think about
it ;)
Comment 18 Raphael Higino 2004-08-15 19:10:13 UTC
I like Danilo's solution. If it is well commented I think translators will
understand. Even I could understand it.

I just think it should verify whether the choice string was translated only to
"hours" or "mins". If it is other else than those the applet would not pluralize
it in hours by default.

Backing on my previous post, I asked my mom, who is a Portuguese teacher, and
she told me that in Portuguese when the subject is a composed subject as in this
case (X hours and Y minutes) it is always pluralized, even if both are singular.
Then that problem I exposed is not really a problem in Portuguese, although it
still remains in other languages.
Comment 19 Danielle Madeley 2004-08-16 04:30:43 UTC
If it's not a problem in Portuguese or Serbian, then I don't really want to
touch it now. Unless of course, some other translator has a problem. It's
something to look at for the next release cycle though.
Comment 20 Danielle Madeley 2004-09-21 06:59:19 UTC
This bug can probably be closed now.