• Członkowie 3 posty
    12 marca 2024 22:15

    Hej, hej. To mój pierwszy post na tym forum, więc zaczynam od przywitania: cześć wszystkim!

    Nie jestem programistą, chociaż pewne podstawy ogarniam. Zajmuję się za to hobbystycznie tłumaczeniem aplikacji dla Linuksa i ostatnio zabrałem się za jedną napisaną w Pythonie.

    Angielskie stringi są wpisane bezpośrednio w kod jako fallback, a ich tłumaczeniem zajmuje się gettext na podstawie plików .po. Przykład:

    def classify_uv_index(uv_index):
        if uv_index <= 2:
            return _("Low")
        elif uv_index <= 5:
            return _("Moderate")
        elif uv_index <= 7:
            return _("High")
        elif uv_index <= 10:
            return _("Very High")
        else:
            return _("Extreme")
    

    Oczywiście problem w języku polskim jest ten, że słowa odmieniamy i „high” może oznaczać „wysoki”, „wysoka” oraz „wysokie”, nie mówiąc już o przypadkach.

    Niestety, nie można po prostu w pliku pl.po zdefiniować różnych wersji tłumaczenia, rozróżniając je jedynie inną ścieżką do pliku i numerem linii w komentarzu – przy budowaniu aplikacji wyskakują błędy duplikacji stringów.

    Żeby to rozwiązać, zacząłem czytać dokumentację bilioteki gettext i znalazłem informację o możliwości dodania kontekstu. Przerobiłem powyższy fragment kodu zgodnie z tym, co wyczytałem, dodając kontekst dla ciągów, które w aplikacji występują więcej niż jeden raz:

    def classify_uv_index(uv_index):
        if uv_index <= 2:
            return gettext.pgettext("uvindex", "Low")
        elif uv_index <= 5:
            return gettext.pgettext("uvindex", "Moderate")
        elif uv_index <= 7:
            return gettext.pgettext("uvindex", "High")
        elif uv_index <= 10:
            return _("Very High")
        else:
            return _("Extreme")
    

    Wygenerowałem xgettext --keyword=pgettext:1c,2 świeży plik .pot i na jego podstawie zaktualizowałem przy użyciu msgmerge plik pl.po, gdzie przetłumaczyłem nowe stringi:

    msgctxt "uvindex"
    msgid "Low"
    msgstr "Niski"
    
    msgctxt "uvindex"
    msgid "Moderate"
    msgstr "Umiarkowany"
    
    msgctxt "uvindex"
    msgid "High"
    msgstr "Wysoki"
    

    Po tych zmianach aplikacja buduje się bez problemów, instaluje i odpala się z polskim tłumaczeniem. Niestety, wszystkie stringi, które miały podany kontekst, wyświetlają się bez tłumaczenia, w wersji fallback z pliku .py.

    Siedziałem nad tym kilka godzin, przeglądając różne strony, dokumentacje i gapiąc w kod, ale nie udało mi się tego naprawić.

    Co robię źle? Jak mogę to zdebugować? Przy uruchamianiu z terminala nie ma słowa o błędach.

    Z góry dziękuję za wszelkie podpowiedzi!

  • Członkowie 3 posty
    13 marca 2024 10:57

    Żeby sprawdzić, czy to, co robię w ogóle „trzyma się kupy” napisałem mikro-program używający tej samej składni:

    import gettext
    gettext.bindtextdomain('gt', 'po')
    gettext.textdomain('gt')
    
    print("High as in high UV index:",gettext.pgettext("uvindex","High"))
    print("High as in high humidity:",gettext.pgettext("humidity","High"))
    print("High as in high polution:",gettext.pgettext("polution","High"))
    

    Wygenerowałem plik .pot, przetłumaczyłem plik .po, wygenerowałem plik .mo. Wszystko działa:

    ❯ python3 GettextTest.py
    High as in high UV index: Wysoki
    High as in high humidity: Wysoka
    High as in high polution: Wysokie
    

    Najwyraźniej w samej apce, którą chciałem przetłumaczyć, dzieje się coś, czego nie widzę/nie rozumiem. Chyba po prostu wyślę devowi informacje o pgettext, kontekście, msgctxt itd. i niech sam przerabia swoją aplikację, o ile chce mieć ją porządnie tłumaczoną.

  • 13 marca 2024 21:45

    Cześć, fajnie że dołączyłeś do forum :)
    Wydaje mi się że warto sprawdzić czy w tej aplikacji importy i ustawienia są takie same jak w twoim przykładzie, czyli

    import gettext
    gettext.bindtextdomain('gt', 'po')
    gettext.textdomain('gt')
    

    i czy kroki jakie wykonywałeś przy generowaniu i kompilowaniu tłumaczenia są dokładnie takie same. Zwróć też uwagę na wersje pythona, jeśli są różne to może to mieć znaczenie.

  • Członkowie 3 posty
    13 marca 2024 22:39

    Dzięki wielkie za odpowiedź!

    Zainspirowany sugestią ustawień gettextu zajrzałem jeszcze raz do kodu apki i to, co przy wcześniejszym pobieżnym przejrzeniu wziąłem za ustawienia gettext, było ustawieniami locale. Fragment

    locale.bindtextdomain('mousam', localedir)
    locale.textdomain('mousam')
    

    mój durny mózg uznał za

    gettext.bindtextdomain('mousam', localedir)
    gettext.textdomain('mousam')
    

    Ech. Dziękuję jeszcze raz za pomoc.