Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Translations problem with Python3 #1

Open
gbtami opened this issue Oct 16, 2015 · 13 comments
Open

Translations problem with Python3 #1

gbtami opened this issue Oct 16, 2015 · 13 comments

Comments

@gbtami
Copy link

gbtami commented Oct 16, 2015

While I'm trying pygobject-locale with hungarian translations, it's fully working with Python 2.7 but only half working with Python 3.4 on Windows7. I see my translations in console, but not in the GUI.
I use pygobjectwin32 rev.22
27
34

@tobias47n9e
Copy link
Owner

Hi! I also tried getting this to work on Python 3.4, but so far I did not have any luck debugging the issue. I posted some more information abou the problem in the following places:

I think the GUI should translate when you leave away all non-ASCI characters in the Hungarian translation. I think it fails on the first non-ASCII character it finds.

I will test this again when the 3.18 files are released. The issue might be a bug in the 3.14 binaries that nobody ever noticed.

Let me know if you make any progress!

@tobias47n9e
Copy link
Owner

By the way. How did you package this for Windows?

@gbtami
Copy link
Author

gbtami commented Oct 16, 2015

I can't reproduce any problems of yours linked above (as you can see on my screenshots).
I tried pygobject-locale in place (no packaging) with this modification:

@@ -1,3 +1,5 @@
+# -*- coding: UTF-8 -*-
+
 from gi.repository import Gtk
 import gettext
 import locale
@@ -20,7 +22,8 @@ if sys.platform.startswith('win'):

     # Set LOCALE_DIR for MS Windows
     import ctypes
-    LIB_INTL = abspath(join(WHERE_AM_I, "../gnome/libintl-8.dll"))
+    import site
+    LIB_INTL = os.path.join(site.getsitepackages()[1], "gnome", "libintl-8.dll")
     libintl = ctypes.cdll.LoadLibrary(LIB_INTL)
     lc = locale.setlocale(locale.LC_ALL, "")
     print(lc) # Returns local. On W e.g. German_Germany.1252

@gbtami
Copy link
Author

gbtami commented Oct 16, 2015

I'v removed all non ASCII chars in .po, but got nothing better.

@tobias47n9e
Copy link
Owner

I'v removed all non ASCII chars in .po, but got nothing better.

Then that must have been the behaviour of either rev14, rev19, rev20 or rev21. I tested so many combinations that I can't remember which one did what. I do hope that eventually someone will look at the bug I filed on bugzilla.gnome. It would be really helpful to get better return values for some of these calls. But otherwise I am just hoping that the 3.18 windows package will get better results.

@gbtami
Copy link
Author

gbtami commented Oct 17, 2015

Here is my workaround I will use in PyChess until this get fixed upstream:

if PY3 and sys.platform == "win32":
    for obj in self.builder.get_objects():
        if (not isinstance(obj, Gtk.SeparatorMenuItem)) and hasattr(obj, "get_label"):
            label = obj.get_label()
            if label is not None:
                obj.set_label(_(label))
        elif hasattr(obj, "get_title"):
            title = obj.get_title()
            if title is not None:
                obj.set_title(_(title))

@tobias47n9e
Copy link
Owner

I tried the function now, and it works perfectly: 796b6ba

Thanks for sharing the workaround!

I will also add comments to the bug reports and see if the bug can be isolated now.

@gbtami
Copy link
Author

gbtami commented Oct 24, 2015

Just for completeness (and maybe someone want to use it somewhere), later I
added another if block to this workaround, because some Gtk widgets can
have both label and and tooltip text.
(See in the bottom of
https://github.com/pychess/pychess/blob/master/lib/pychess/System/uistuff.py
)

if hasattr(obj, "get_tooltip_text"):
text = obj.get_tooltip_text()
if text is not None:
obj.set_tooltip_text(_(text))

On Sat, Oct 24, 2015 at 3:16 PM, Tobias Schönberg notifications@github.com
wrote:

I tried the function now, and it works perfectly: 796b6ba
796b6ba

Thanks for sharing the workaround!

I will also add comments to the bug reports and see if the bug can be
isolated now.


Reply to this email directly or view it on GitHub
#1 (comment)
.

@ghost
Copy link

ghost commented May 28, 2016

I found your workaround @gbtami when I was troubled by the same translation bug, but had some issues with it. First as a fellow Python programmer I wasn't too thrilled by the unidiomatic type checking. Then finding all the methods that handle text in Gtk+ can be a bit of a hassle. On a cursory search I found there are some more markup handling methods that would also need to be added to the workaround. And finally, we can't be sure that it's appropriate to translate all the text collected from these methods. Names, places, technology names, trademarks and more might be accidentally translated.

Still, the idea behind the workaround is great, if the API doesn't do it well, do it yourself. So I decided to follow it, but from a different angle. I used one of the many python xml modules in the standard library to open the glade xml file myself, I looked for each instance of the translatable attribute, translated the text associated with it, and then fed the builder with the updated string. I'm not too happy about having to use a BytesIO object here, but the xml module used only outputs the xml_declaration if written to a file, so a compromise was made. I'm confident this is a more idiomatic and solid workaround.

import xml.etree.ElementTree as ET
from io import BytesIO

def make_builder(self, gui_file):
    if sys.platform == "win32":
        tree = ET.parse(gui_file)
        for node in tree.iter():
            if 'translatable' in node.attrib:
                node.text = _(node.text)
        temp_file = BytesIO()
        tree.write(temp_file, encoding='utf-8', xml_declaration=True)
        xml_text = temp_file.getvalue().decode()
        return Gtk.Builder.new_from_string(xml_text, len(xml_text))
    else:
        return Gtk.Builder.new_from_file(gui_file)

@gbtami
Copy link
Author

gbtami commented Jun 21, 2016

@xor thank you for your more solid workaround. I'v applied it to PyChess with a little modification. I had to "fix" Gtk.Image nodes pixbuf text to let the Builder find .png images.
pychess/pychess@1f05788

@gbtami
Copy link
Author

gbtami commented Jun 28, 2016

I had to change temp_file from BytesIO() to a real file to let some buttons (f.e. Cancel) work in our https://github.com/pychess/pychess/blob/master/glade/newInOut.glade
https://github.com/pychess/pychess/blob/master/lib/pychess/System/uistuff.py#L522

@romaia
Copy link

romaia commented Sep 5, 2017

@xor You are a life saver. One year later an I am having this issue with our project. Using PyGI AIO 3.24.1 rev1

async-jenkins pushed a commit to stoq/kiwi that referenced this issue Sep 6, 2017
Windows with python3 and Gtk3/pygi has this really nasty bug that translations
are actually working, but somehow the enconding is messed up by Gtk. This might
be fixed in newer versions of Gtk/pygi, but currently, we are stuck with 3.24
on Windows.

The idea of the workaround here is to parse the glade xml, and translate in
python all translatable strings, dump the xml on a temp file and then
load the interface from this tempfile. Works like a charm

Other references from a user with the same issue
https://stackoverflow.com/questions/32037573/
https://sourceforge.net/p/pygobjectwin32/tickets/22/
https://bugzilla.gnome.org/show_bug.cgi?id=753991

And the source of the workaround

tobias47n9e/pygobject-locale#1 (comment)

Change-Id: I7f381e4de0ad9796e27d4c8e1c2c9e2331f25e91
@gbtami
Copy link
Author

gbtami commented Nov 28, 2017

A little bit shorter version without using io.BytesIO and .decode()

import xml.etree.ElementTree as ET

def make_builder(self, gui_file):
     if sys.platform == "win32":
         tree = ET.parse(gui_file)
         for node in tree.iter():
             if 'translatable' in node.attrib:
                 node.text = _(node.text)
         xml_text = ET.tostring(tree.getroot(), encoding='unicode', method='xml')
         return Gtk.Builder.new_from_string(xml_text, -1)
     else:
         return Gtk.Builder.new_from_file(gui_file)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants