New i18n interface for KDE 4, second try

Chusslove Illich caslav.ilic at gmx.net
Tue Oct 25 15:25:16 BST 2005


After some more toying with the code, here is the summary.

Just a reminder: the new interface is needed if we want to capture 
arguments which replace the %NN placeholders in an i18n call, and that is 
needed because we want to employ translator-side scripting of some 
grammar-wise nasty messages.

Basic idea was to make a new class derived from QString, which has 
overridden arg() methods. This was discussed a lot, and while it would 
make least impact on existing i18n practices, almost preserving source 
compatibility, it had a need for some hacks (because QString was not 
designed for inheritance). However, due to its non-intrusivity, I feel 
this still to be an option, so I mention it here.

The other feasible idea was to make a new class, say named KTrString, but 
not derived from QString and without any implicit conversions to QString, 
and therefore with a special method to finalize translation, i.e. like:

i18n("Blah, blah: %1 %2").arg(foo).arg(bar).toString();

This is a very clean solution, and it also allows to check at runtime 
whether all arguments have been supplied before call to toString(), so 
that programmer can be warned of possible problem if he does something 
like this:

QString msg = i18n("Blah, blah: %1 %2").toString();
msg = msg.arg(foo).arg(bar);

However, since the mandatory extra toString(), even when no arguments are 
present, is kind of stupid, there can also exist a set of simple templates 
which mimick variable argument list, so that this can be used:

i18n("Blah, blah: %1 %2", foo, bar); // ordinary
i18nc("This is for...", "Blah, blah: %1 %2", foo, bar); // context
i18np("One thingy with %1", "%n thingies with %1", n, whatnot); // plural

where i18n[cp]() templates would look like:

class KTrString {
  ...
  template <typename A1, ..., typename An>
  friend i18n (const char *text, const A1 &a1, ..., const An &an) {
    KTrString(text).arg(a1).....arg(an).toString();
  }
  ...
  template <typename A1, ..., typename An>
  friend i18nc (const char *context, const char *text,
                const A1 &a1, ..., const An &an) {
    KTrString(context, text).arg(a1).....arg(an).toString();
  }
  ...
  template <typename A1, ..., typename An>
  friend i18np (const char *singular, const char *plural, int n,
                const A1 &a1, ..., const An &an) {
    KTrString(singular, plural, n).arg(a1).....arg(an).toString();
  }
  ...
}

Templates would be declared up to some limited number of arguments, so over 
that, one would have to use ...arg()...toString() syntax, with special 
ki18n() calls which would really return a KTrString. But these are very, 
very rare - I found seven messages with more than %8, two with more than 
%10.

The other case when one would want to use ki18n[pc]() is if split is really 
convenient, like:

KTrString msg = ki18n("Blah, blah: %1");
...
wiggy->doSomething(msg.arg(foo).toString());

(But this practice should anyway be discouraged.)

Additional nice thing with the templates is that extra .arg(...) sugar can 
be dropped.

I just don't know if some obscure compilers would choke with required 
template instantiations.

I have patched together a perl script to convert the current KDE code to 
template formulation. It seems to be doing its job correctly, albeit 
embarrassingly slow :) As a test, in branch 3.5, I've converted and 
compiled libs, base, pim, network, graphics, multimedia and sdk, without 
any (argh, *almost* any) problems.

There was one case when compiler didn't want to instantaniate a template 
when one argument was an unnamed enumeration (I've checked, this is 
according to standard; how many dark corners are there in this language?), 
and one pathological case in Kontact which had 25 arguments to a 
message :) Yet, this makes even less problems than the inherited solution, 
which requires explicit casts in several places (mostly connected with 
ternary ops)...

As for xgettext support, since recently both approaches are fully supported 
for extraction by xgettext from Gettext CVS, so this element can be 
factored out of consideration.

-- 
Chusslove Illich (Часлав Илић)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://mail.kde.org/pipermail/kde-core-devel/attachments/20051025/3577ae46/attachment.sig>


More information about the kde-core-devel mailing list