[PyKDE] Feedback Needed on Possible tr() Changes
Jan L. Nauta
jln at magentammt.com
Mon May 26 09:31:01 BST 2003
Or another alternative would be:
4. Your implementation of QObject::tr() now does a dynamic lookup of the
class name. You could use the QTranslator::contains() method to check if a
particular context/string is available in a translator, starting with the
class. If the class doesn't have a translation, check with the base
class(es)...
<code>
if python_translator installed :
class = class type of self
while class :
if python_translator.contains(class.name, string) :
return translated string
class = base class
previous implementation
</code>
All you need now is a PyQt call to set the python_translator. If the
python_translator isn't set, the 'old' implementation is used. This way no
sources have to be changed, and the new behavious is only available if
requested.
Regards, jln
> I think people have hinted to me before about this, but I've only just
> properly understood the problem. I suspect that it is impossible
> for PyQt to
> implement QObject.tr() properly - although I may get lucky with
> SIP v4's use
> of metaclasses. I've made a couple of attempts in the past, but
> it seems that
> the current implementation may not the best design decision I've
> ever made.
>
> Translation in Qt is based on the string to translate and a context. The
> context is usually the name of the class from which tr() is
> called. Each C++
> class that contains the Q_OBJECT macro has it's tr() method created
> automatically by moc. Each generated tr() has the proper context
> hardcoded.
> It is very difficult/impossible to emulate this behaviour in PyQt
> for Python
> classes that extend C++ classes.
>
> Note that there is a workaround for all this. Just use...
>
> qApp.translate("Context","String")
>
> ...instead of calls to tr().
>
> At the moment I see 3 options...
>
> 1. Current Unpredictable Option
> The current implementation uses the name of the class of the
> instance as the
> context. The problem is then that, if the class is further
> sub-classed, the
> context changes. An example (ignoring calls to __init__)...
>
> class A(QObject):
> def hello(self):
> return self.tr("Hello")
>
> class B(A):
> pass
>
> class C(A):
> pass
>
> a = A().hello() # Context is "A"
> b = B().hello() # Context is "B"
> c = C().hello() # Context is "C"
>
> ...which requires 3 translations of the string. The problem is at
> its worse if
> A is a class generated by pyuic.
>
> 2. Old Predictable Option
> The original implementation had an automatically generated tr() for each
> wrapped QObject sub-class. This meant that the context was
> correct for those,
> but incorrect for any Python sub-class where it was the most
> recent C++ in
> the hierarchy. For example...
>
> class A(QObject):
> def hello(self):
> return self.tr("Hello")
>
> class B(QObject):
> def welcome(self):
> return self.tr("Hello")
>
> a = A().hello() # Context is "QObject"
> b = B().welcome() # Context is "QObject"
>
> ...which (I think) has the consequence of creating one string for
> translation
> when, perhaps, there should be two. Also, I'm not sure if pylupdate will
> determine the correct context.
>
> 3. New Clumsy Option
> Another option is to dump the problem onto the application developer. A
> Q_OBJECT() method could be added to QObject that does the same job as the
> Q_OBJECT macro and creates the tr() method with the correct context
> hardcoded. For example...
>
> class A(QObject):
> def __init__(self):
> QObject.__init__(self)
> self.Q_OBJECT(A)
>
> def hello(self):
> return A.tr("Hello")
>
> class B(A):
> def __init__(self):
> A.__init__(self)
> self.Q_OBJECT(B)
>
> def goodbye(self):
> return B.tr("Goodbye")
>
> b = B()
> b.hello() # Context is "A"
> b.goodbye() # Context is "B"
>
> ...but note that you must explicitly call the class specific tr() and not
> self.tr() - which I feel means you might as well call
> qApp.translate() and
> forget the added complexity of Q_OBJECT().
>
> Note that whatever option is used, I will fix pyuic so that
> generated forms
> get the context right.
>
> Each option has its advantages and disadvantages - developers are
> currently
> dealing with Option 1, Option 2 is probably the least confusing.
>
> Comments and other suggestions welcome.
>
> Phil
>
> _______________________________________________
> PyKDE mailing list PyKDE at mats.imk.fraunhofer.de
> http://mats.imk.fraunhofer.de/mailman/listinfo/pykde
>
More information about the PyQt
mailing list