Important: Please read the Qt Code of Conduct -

How to use pyside6-lupdate?

  • Hi!
    I'm working on an small PySide6 project. I upgraded to 6.2.0 this morning in order to use i18n tools. But I can't find a way to use lupdate...

    First attempt
    I tried pyside6-lupdate with being:

    SOURCES       = atb/
    FORMS         = ui/main_window.ui
    TRANSLATIONS  = ui/i18n/atb_fr.ts

    It spawns a weird utf8 error :

      File "[...]lib\site-packages\PySide6\scripts\", line 72, in qt_tool_wrapper
        msg = err.decode("utf-8")
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8a in position 15: invalid start byte

    I commented out this .decode("utf-8") and found that it concealed a real error message: something like "the specified path does not exist" (translated from french), but I double-checked every pathes.

    Second try
    With no project file, I tried to put everything on the command line. I got no errors but no .ts file were created...

    $ pyside6-lupdate -extensions py,ui ui/ atb/ -ts ui/i18n/atb_fr.ts
    Scanning directory 'ui/'...
    Scanning directory 'atb/'...
    $ ls -l ui/i18n/
    total 0

    Third try
    Looking for my .ts file, I stumbled upon the linguist example in lib/site-packages/PySide6/examples/widgets/linguist/ and I tried to follow it.
    I made a similar .pyproject file:

        "files": ["atb/", "ui/main_window.ui", "ui/i18n/atb_fr.ts"]


    $ pyside6-lupdate -project atb.pyproject
    Error: lupdate error: Missing keys in project description: projectFile.

    I'm feel a bit lost... how should I set up i18n for PySide6?

    Dev environment : Windows 10, Python 3.7.4, PySide 6.2.0 installed in a virtual env

    Thanks for your help!

  • @gbassiere, I'm not very experienced with i18n in Qt but I use it in my project so probably I may help you here.
    First of all - the most recent version of lupdate says that pro-files usage will be deprecated. So, keep it in mind trying your and my examples.

    I created my pro-file some time ago so don't remember all details but I have only SOURCES and TRANSLATIONS there. I don't use FORMS as ui-files are converted into python code with help of uic. If you load them directly from your code - probably it is required.

    Then I run lupdate -no-obsolete now, without extra options, it creates ts-files based on py-files list provided in SOURCES.
    So, your "First attemt" looks most correct for me.

    And just one more thought - as you are on Windows and have this error "UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8a in position 15: invalid start byte" - I suspect that lupdate may expect that your py-files will use UTF-8 encoding. But most probably Windows saves them in your French code page (probably cp1252)

  • Hi @StarterKit, thanks for your help!

    I've retried with .pro file using -no-obsolete option and removing FORMS entry in But it doesn't solve the problem. I get the same error.

    Thanks for the tip about compiled ui files. I agree with you, there's no need of translating .ui files since their compiled Pyhton version will be translated.

    Can you confirm that pathes in .pro files are unix-style (I mean with regular '/') and relative to the .pro file? From the docs, I believe most people generate the .pro file with QMake but I don't have this command since I'm in a PySide environment (rather than regular Qt). The documentation is unfortunately very poor about writing this file manually.

    By the way, you seem to use lupdate command, how did you get it? If I install PySide6 in a fresh virtual environment, I just get pyside6-lupdate... Did you tweak your $PATH to include lib/site-packages/PySide6?

    Regarding Unicode, you're right about Windows but I develop under PyCharm IDE which makes up for Windows flaws, it is configured to always use utf-8.

    But the unicode problem is not in my files, the Python exception is thown in qt_tool_wrapper() in PySide6/scripts/, line 72:

    msg = err.decode("utf-8")

    Here, err is the error message returned by the subprocess which actually run lupdate. If I comment out .decode("utf-8"), I can see that it is a Windows error message:

    $ pyside6-lupdate.exe -no-obsolete
    Error: b"Le chemin d'acc\x8as sp\x82cifi\x82 est introuvable.\r\n"
    while executing '[...]lib\site-packages\PySide6\lupdate -no-obsolete'

    The error message is in french (since it is my OS language), it translates to something like "the specified path does not exist" or "the system cannot find the specified path". But I'm sure that the path exists!

  • Hi @gbassiere
    I think different names lupdate and pyside6-lupdate are simply because different operational systems. I.e. your pyside6-lupdate looks completely fine for me. I saw this kind of name difference before and it didn't have impact.

    On my windows machine I also have pyside6-lupdate. I checked it from command line and it works:

    h:\projects\test_i18n>c:\<full_path>\Python38\Scripts\pyside6-lupdate.exe -ts fr.ts
    Updating 'fr.ts'...
        Found 1 source text(s) (1 new and 0 already existing)

    I got fr.ts file generated. With pro-file I also got Error: The system cannot find the path specified.
    I checked different options - full path, short path, quoted names, with / and \ path separators... I have no idea what is wrong but I confirm - it raises path not found error on Windows while I have no such problems on Linux with the same or very similar pro-file.

  • OK, I finally managed to have a satisfactory behaviour for UI files :

    $ pyside6-lupdate.exe -recursive -extensions ui ui/ -ts ui/i18n/atb_fr.ts
    Scanning directory 'ui/'...
    Updating 'ui/i18n/atb_fr.ts'...
        Found 13 source text(s) (13 new and 0 already existing)

    It works as well without the -extensions ui parameter. Fine.

    For Python files, it is bit more complicated.

    Parameter -recursive doesn't seem to work. I believe files are found but .translate() is not recognized in it.

    $ pyside6-lupdate.exe -recursive atb/ -ts ui/i18n/atb_fr.ts
    Scanning directory 'atb/'...
    Updating 'ui/i18n/atb_fr.ts'...
        Found 0 source text(s) (0 new and 0 already existing)

    With explicit -extensions parameter, my Python files do not even seem to be found

    $ pyside6-lupdate.exe -recursive -extensions py atb/ -ts ui/i18n/atb_fr.ts
    Scanning directory 'atb/'...

    But if I directly point to a Python file with message to be translated, it works

    $ pyside6-lupdate.exe atb/views/ -ts ui/i18n/atb_fr.ts
    Updating 'ui/i18n/atb_fr.ts'...
        Found 2 source text(s) (2 new and 0 already existing)

    I can always resort to good old find command but it's a bit cumbersome:

    $ find atb/ -name \*.py -exec pyside6-lupdate.exe '{}' -ts ui/i18n/atb_fr.ts \;
    Updating 'ui/i18n/atb_fr.ts'...
        Found 0 source text(s) (0 new and 0 already existing)
    Updating 'ui/i18n/atb_fr.ts'...
        Found 0 source text(s) (0 new and 0 already existing)
    Updating 'ui/i18n/atb_fr.ts'...
        Found 2 source text(s) (2 new and 0 already existing)
    Updating 'ui/i18n/atb_fr.ts'...
        Found 0 source text(s) (0 new and 0 already existing)

  • I also notice that lupdate is picky about what is actually a string to be translated. Examples below:

    # This will be detected by `lupdate`"Lorem ipsum...")
    # also this:
    QCoreApplication.translate("MainWindow", "Lorem ipsum...")
    # but neither this:
    QCoreApplication.translate("MainWindow", b"Lorem ipsum...")
    # nor this:
    QCoreApplication.translate("MainWindow", u"Lorem ipsum...")

    The funny thing is that uic generate the latter form (which obsolete but remain supported, PEP414). Fortunately, I can get collect translation from the UI file.

  • @gbassiere yes, uic generates u"string", but apparently my lupdate works fine with them as my UI is translated...

Log in to reply