Red Hat Bugzilla – Bug 524990
setroubleshoot should use ngettext
Last modified: 2009-10-01 16:49:35 EDT
num_of_times = _("s")
if alert.report_count == 1:
num_of_times = ""
start_label_text = _("This alert has occurred <b>%d time%s</b> since %s") % (alert.report_count, num_of_times, start_date.format(date_format))
are highly inappropriate and don't work for languages other than English.
Please use ngettext instead, see bug #467603 for an example.
Fixed in setroubleshoot-2_2_30-1_fc12
Daniel, thanks for picking this up so quickly. Unfortunately, this is just another hack, admittedly less bad than the last one from i18n point of view. It still might not work well for some languages.
I'm reopening this so you can fix it properly using ngettext when you have some more time.
start_label_text = gettext.ngettext("This alert has occurred <b>%d time</b> since %s", "This alert has occurred <b>%d times</b> since %s", alert.report_count) % % (alert.report_count, start_date.format(date_format))
That's the idea, and it might "just work", but I don't get the inner workings of python, automake, and intltool.
More typically an alias for ngettext() is made, like
start_label_text = P_("This alert has occurred <b>%d
time</b> since %s", "This alert has occurred <b>%d times</b> since %s",
alert.report_count) % % (alert.report_count, start_date.format(date_format))
with P_() bound to gettext.ngettext() wherever _() is bound to gettext.gettext()
Then, you need to tell intltool how to extract these messages by passing some extra args to xgettext. From the intltool README:
Changing keywords used in xgettext invocation
If you need to change default keywords used to extract messages from
source code, you need to add variable XGETTEXT_KEYWORDS to
Makefile.in.in file inside directory where intltool-update is run
--- start ----
XGETTEXT_KEYWORDS = --keyword --keyword=P_
--- end ----
Default keywords xgettext looks for if no XGETTEXT_KEYWORDS is defined
are _, N_ and U_.
So, to your po/Makefile.in.in you'd need to add something like
XGETTEXT_KEYWORDS = --keyword=P_:1,2
As I said, I'm not an expert, so some details are probably missing...
Found more candidates:
browser.py: return _("%d days ago") % days
seapplet.c: sprintf(msg, _("Since your last login, there are %d new security alerts to view."), yellow+red);
seapplet.c: sprintf(msg, _("Since your last login, there are %d new security alerts to view. %d of the alerts may be very serious security violations."), yellow+red, red);
seapplet.c: sprintf(title, _("%d New Security Alerts"), yellow+red);
Note that the second message in seapplet.c is probably best broken down, the added benefit being that the first sentence already appears earlier, will be recognized as such by xgettext during extraction, and will need to be translated only once.
Created attachment 362563 [details]
C ngettext patch
Attaching a proposed ngettext patch for the C part, just missing the Python bit (could figure out where gettext is imported and _() bound).
Dan: this is only somewhat tangentially related. In the python code we were using somewhat of a hack to get around the fact the default encoding in Python was hardcoded to ascii instead of utf-8. This required use to tell gettext() to return utf-8 in Python str object instead of UCS-4 in Unicode objects.
Since that code was first written we've figured out a way to force Python into the correct utf-8 default encoding mode. Which means we can get rid of the old hack and clean up some misleading comments in the code.
This is really just a FYI, it won't affect the output, but at some point should be cleaned up and use the "correct" idoms.
Created attachment 362568 [details]
Improved C ngettext patch
Splitting the two strings, second sentence form might depend on the count in some more languages like it does for Serbian.
All this is fixed in setroubleshoot-2.2.31-1.fc12
But we still are not seeing the actual translations in the code. The problem seems to be that we are shipping the viewer in one package "setroubleshoot" and the text in another package "setroubleshoot-plugins"
And I think the text is not being translated because of this.
Hm, now we're missing desktop and glade strings...
Btw, don't think putting XGETTEXT_KEYWORDS in Makefile.am is appropriate, the README clearly indicates po/Makefile.in.in. Also the --keywords option without any keywords overrides the default keywords, which is not what one would want I think (I'd use only --keyworrd=_P:1,2 as in my patch). Unfortunately neither of these changes bring back the desktop and glade strings, could really use an intltool expert here.
One plural string also slipped through the net:
--- setroubleshoot-2.2.32/src/browser.py 2009-09-25 22:13:40.168164466 +0100
+++ setroubleshoot-2.2.32_ngettext/src/browser.py 2009-09-25 22:18:17.618165876 +0100
@@ -736,7 +736,7 @@
if days == 1:
- return _("%d days ago") % days
+ return P_("%d day ago", "%d days ago", days) % days
Have you checked to see that locale dir is correct and the domain names match?
John, they are missing during string extraction to pot. When XGETTEXT_KEYWORDS is commented out, the extraction works as before, without the plural strings of course.
I wrote up this guide to localization and i18n. It tries to give a concise overview, a lot of the other guides are hard to follow IMHO,
re comment #12, so the pot files are empty?
They are not empty, just missing/skipping desktop and glade files, although they are listed in POTFILES.in. Strings from Python and C files still get extracted. See e.g.
It seems that it has been fixed in this commit:
I believe this is fixed in setroubleshoot-2.2.33-1.fc12.x86_64
Yep, just missing one more P_() marked string (see bottom of comment #10).
Thanks Daniel and Piotr.
No because if it happened 1 day ago, the tool prints "Yesterday" So it will only print the plural.
Some languages have more than one plural form.
Sure Daniel, that makes perfect sense, but again, only for English. For other languages you could use different plural word forms for "days" even for numbers greater than 2. For example, in Serbian "3 dana", but "21 dan" (same is singular because it ends wit a 1). Plural rules get even more complex for other languages, as mentioned in the link in the opening comment.
This is the whole point of using ngettext. You as a developer do not have to, and indeed shoudn't think about strings with plurals. As they say: "assumption is..." ;)
Last change confirmed in hg, thank you very much Daniel!