[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