Search code examples
pythonpyqttranslationpyqt5qt-linguist

QT_TRANSLATE_NOOP disambiguation with pylupdate


I'm trying to use pylupdate to create translation files.

import sys
from PyQt5 import QtCore
from PyQT5.QtCore import QT_TRANSLATE_NOOP
_translate = QtCore.QCoreApplication.translate


if __name__ == '__main__':
app = QApplication(sys.argv)
qt_translator = QtCore.QTranslator(app)
list_translate = [
    QT_TRANSLATE_NOOP("test", "fake"), 
    QT_TRANSLATE_NOOP("test", "thing"), 
    QT_TRANSLATE_NOOP("test", "something")
]
for item in list_translate:
    _translate("test", item, "1")
_translate("test", "other thing")

And from this I found QT_TRANSLATE_NOOP. But I'm unable to figure out how to have pylupdate keep use the disambiguation comment. Every time I run it, it marks the one I have in my file as obsolete and makes a new entry. Is there a way to specify the comment in the literal as well?

.ts to start:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0">
<context>
    <name>test</name>
    <message>
        <location filename="test.py" line="17"/>
        <source>other thing</source>
        <translation>tran</translation>
    </message>
    <message>
        <location filename="test.py" line="11"/>
        <source>fake</source>
        <comment>1</comment>
        <translation>slate</translation>
    </message>
    <message>
        <location filename="test.py" line="12"/>
        <source>thing</source>
        <translation>something</translation>
    </message>
    <message>
        <location filename="test.py" line="13"/>
        <source>something</source>
        <translation>still something</translation>
    </message>
</context>
</TS>

.ts file after running

pylupdate5 -verbose test.py -ts translate/test.ts

notice line 14:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS><TS version="2.0">
<context>
    <name>test</name>
    <message>
        <location filename="test.py" line="17"/>
        <source>other thing</source>
        <translation>tran</translation>
    </message>
    <message>
        <location filename="test.py" line="11"/>
        <source>fake</source>
        <comment>1</comment>
        **<translation type="obsolete">slate</translation>**
    </message>
    <message>
        <location filename="test.py" line="12"/>
        <source>thing</source>
        <translation>something</translation>
    </message>
    <message>
        <location filename="test.py" line="13"/>
        <source>something</source>
        <translation>still something</translation>
    </message>
    <message>
        <location filename="test.py" line="11"/>
        <source>fake</source>
        <translation type="unfinished">slate</translation>
    </message>
</context>
</TS>

Solution

  • Both PyQt4 and PyQt5 are missing QT_TRANSLATE_NOOP3, which provides a third argument which takes a comment. This is obviously a bug (which should be reported on the pyqt mailing list), but it is easy enough to work around. Fortunately, pylupdate will correctly parse a three-argument QT_TRANSLATE_NOOP even though PyQt doesn't provide the actual function itself.

    Below is a working demo. The .ts file needs to be compiled first using:

    lrelease-qt5 test.ts -qm test.qm
    

    test.py file:

    import sys
    from PyQt5.QtCore import QCoreApplication, QTranslator
    _translate = QCoreApplication.translate
    
    def QT_TRANSLATE_NOOP(context, source, comment=None):
        return source
    
    if __name__ == '__main__':
    
        app = QCoreApplication(sys.argv)
        translator = QTranslator(app)
        translator.load('test.qm')
        app.installTranslator(translator)
    
        strings = [
            QT_TRANSLATE_NOOP('test', 'object', 'thing'),
            QT_TRANSLATE_NOOP('test', 'object', 'purpose'),
            QT_TRANSLATE_NOOP('test', 'object', 'disagree')
            ]
    
        print('object/thing:', _translate('test', strings[0], 'thing'))
        print('object/purpose:', _translate('test', strings[1], 'purpose'))
        print('object/disagree:', _translate('test', strings[2], 'disagree'))
    

    test.ts file:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE TS><TS version="2.0" language="fr_FR" sourcelanguage="en_GB">
    <context>
        <name>test</name>
        <message>
            <location filename="test.py" line="16"/>
            <source>object</source>
            <comment>thing</comment>
            <translation>objet</translation>
        </message>
        <message>
            <location filename="test.py" line="17"/>
            <source>object</source>
            <comment>purpose</comment>
            <translation>objectif</translation>
        </message>
        <message>
            <location filename="test.py" line="18"/>
            <source>object</source>
            <comment>disagree</comment>
            <translation>objecter</translation>
        </message>
    </context>
    </TS>