Translations: plural forms

Bug #730499 reported by Olivier Tilloy on 2011-03-07
12
This bug affects 1 person
Affects Status Importance Assigned to Milestone
The Charlotte project
Critical
Alex Chiang
unity-2d
Critical
Aurélien Gâteau

Bug Description

(originated from question #148053)

In the trunk of unity-2d, the only translation file currently available is French (fr.po), which is generated/updated by invoking `make update-po`. This file is missing a 'Plural-Forms' header entry, and strings that contain plural forms are missing a 'msgid_plural' entry (they have a 'qt-plural-format' marker though, I’m not sure if it’s used and how).

Note that the source code that is correctly prepared for plural forms, as described at http://doc.qt.nokia.com/i18n-source-translation.html#handling-plurals.

Related branches

Aurélien Gâteau (agateau) wrote :

xgettext has support for Qt format strings through the --qt option. That is why there are some "qt-plural-format" markers. The questions though are:

1. Are plural currently working in our hybrid QTranslator/gettext system?
This can be checked with a unit-test, I am going to give it a try.

2. Does launchpad support these markers?
Subscribing dpm for this question.

Changed in unity-2d:
assignee: nobody → Aurélien Gâteau (agateau)
Changed in unity-2d:
status: New → Triaged
importance: Undecided → Critical
milestone: none → 3.8
Aurélien Gâteau (agateau) wrote :

We have a problem: it is not possible to replace plural handling in QTranslator with a gettext implementation.

More details:
Regular translations are handled by
QTranslator::translate(const char * context, const char * sourceText, const char * disambiguation = 0 ) const

This method is virtual, our GettextTranslator reimplements it to use gettext instead.

Plural translations on the other hand are handled by
QTranslator::translate ( const char * context, const char * sourceText, const char * disambiguation, int n ) const

which is *not* virtual and does not call the other translate() method.

The only solution I can think of is to use gettext directly, ignoring Qt translation system. This requires the following:
- Adjust the C++ code to use gettext functions instead of tr().
- Write QML bindings for the gettext functions.
- Adjust the QML code to use the QML bindings instead of qsTr().
- Adjust update-unity-2d-pot to not use qt keywords (tr and qsTr).
- Get rid of GettextTranslator

El dl 07 de 03 de 2011 a les 11:28 +0000, en/na Aurélien Gâteau va
escriure:
> We have a problem: it is not possible to replace plural handling in
> QTranslator with a gettext implementation.
>
> More details:
> Regular translations are handled by
> QTranslator::translate(const char * context, const char * sourceText, const char * disambiguation = 0 ) const
>
> This method is virtual, our GettextTranslator reimplements it to use
> gettext instead.
>
> Plural translations on the other hand are handled by
> QTranslator::translate ( const char * context, const char * sourceText, const char * disambiguation, int n ) const
>
> which is *not* virtual and does not call the other translate() method.
>
>
> The only solution I can think of is to use gettext directly, ignoring Qt translation system. This requires the following:
> - Adjust the C++ code to use gettext functions instead of tr().
> - Write QML bindings for the gettext functions.
> - Adjust the QML code to use the QML bindings instead of qsTr().
> - Adjust update-unity-2d-pot to not use qt keywords (tr and qsTr).
> - Get rid of GettextTranslator
>

Thanks Aurélien for the detailed analysis and for laying out the current
options.

I've got a quick question. I've got no previous experience with Qt code,
so bear with me if it seem obvious or far-fetched :)

      * Would there not be another way to override
        "QTranslator::translate ( const char * context, const char *
        sourceText, const char * disambiguation, int n ) const" by a
        call to the ngettext function form gettext?

I'm just wondering that there must be a way to do it so that we can use
the work that's already been done. KDE use gettext with Qt code and
handle plural forms, perhaps it might be worth looking at how they do
it.

And for the sake of completeness, to answer the question:
> 2. Does launchpad support these markers?

Launchpad supports all format specifiers that gettext supports. As
gettext supports 'qt-plural-format' as in the example below, this should
not be a problem.

#, qt-plural-format
msgctxt ""
msgid "%n bird(s)"
msgid_plural "%n bird(s)"
msgstr[0] ""
msgstr[1] ""

--
David Planella
Ubuntu Translations Coordinator
www.ubuntu.com / www.davidplanella.wordpress.com
www.identi.ca/dplanella / www.twitter.com/dplanella

Aurélien Gâteau (agateau) wrote :

> * Would there not be another way to override
> "QTranslator::translate ( const char * context, const char *
> sourceText, const char * disambiguation, int n ) const" by a
> call to the ngettext function form gettext?

No, that's not possible because this method is not virtual, so we can't override it.

As for KDE using gettext with Qt code, the main difference is that KDE default translation system is gettext, not Qt. They do have a way to redirect code using Qt translation system to gettext but the vast majority of KDE translations are handled by gettext. I would need to investigate but I am pretty sure KDE redirect code does not handle plural forms as well.

Florian Boucault (fboucault) wrote :

Aurélien's proposal to migrate to gettext entirely is estimated to take 16 hours of work.

David Planella (dpm) wrote :

El dl 07 de 03 de 2011 a les 15:00 +0000, en/na Florian Boucault va
escriure:
> Aurélien's proposal to migrate to gettext entirely is estimated to take
> 16 hours of work.
>

Note that if that is too costly in terms of resources, a workaround is
to rephrase messages so that they do not contain plurals depending on a
variable number of items.

E.g:

        "%d items in the Trash bin"

Would then become the following message, which can be handled by gettext
and tr, instead of ngettext

        "Items in the Trash bin: %d"

But note that this is simply a workaround to be considered as a fallback
to provide at least acceptable translation support in Natty. In order to
provide good native language support, as one of the main Ubuntu values,
we should have proper plural handling, if it's not in Natty, at least in
Oneiric.

--
David Planella
Ubuntu Translations Coordinator
www.ubuntu.com / www.davidplanella.wordpress.com
www.identi.ca/dplanella / www.twitter.com/dplanella

tags: added: charlotte-backport-needed
Daniel Albers (al) wrote :

The way Quassel solved this, was by converting .po files to Qt's .qm format translations during the build stage (http://git.quassel-irc.org/?p=quassel.git;a=blob;f=po/CMakeLists.txt).
This way no custom QTranslator was necessary. Downside is that you cannot ship translations in separate gettext language packages.

Florian Boucault (fboucault) wrote :

Thanks for the tip Daniel. That approach was considered and had 2 downsides:
- it requires work to integrate properly with launchpad translations
- (as you said) you cannot ship translations in the language packages

Changed in unity-2d:
status: Triaged → In Progress
Changed in unity-2d:
status: In Progress → Fix Committed
Alex Chiang (achiang) on 2011-03-22
Changed in charlotte:
milestone: none → m4-rc2
Changed in unity-2d:
status: Fix Committed → Fix Released
Alex Chiang (achiang) on 2011-03-24
Changed in charlotte:
assignee: nobody → Alex Chiang (achiang)
status: New → Triaged
importance: Undecided → High
importance: High → Critical
Florian Boucault (fboucault) wrote :

Fix has been backported from lp:unity-2d (natty) to lp:unity-2d/0.4 (maverick).

Changed in charlotte:
status: Triaged → In Progress
Alex Chiang (achiang) on 2011-03-25
Changed in charlotte:
status: In Progress → Fix Committed
Alex Chiang (achiang) on 2011-03-30
Changed in charlotte:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Related questions