tobias47n9e / pygobject-locale

A test-project that shows how to do pygobject translations that work on Linux and Windows
MIT License
3 stars 0 forks source link

Translations problem with Python3 #1

Open gbtami opened 9 years ago

gbtami commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

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

gbtami commented 9 years ago

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 commented 9 years ago

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

tobias47n9e commented 9 years ago

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 commented 9 years ago

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 commented 9 years ago

I tried the function now, and it works perfectly: https://github.com/tobias47n9e/pygobject-locale/commit/796b6bafd41125c1a87c730ade251d6cc2e23e4d

Thanks for sharing the workaround!

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

gbtami commented 9 years ago

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_tooltiptext((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 https://github.com/tobias47n9e/pygobject-locale/commit/796b6bafd41125c1a87c730ade251d6cc2e23e4d

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 https://github.com/tobias47n9e/pygobject-locale/issues/1#issuecomment-150810602 .

ghost commented 8 years ago

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 _xmldeclaration 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 commented 8 years ago

@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. https://github.com/pychess/pychess/commit/1f057886b66e56bb2f0481a1cd6a16ebb3a962af

gbtami commented 8 years ago

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 commented 7 years ago

@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

gbtami commented 6 years ago

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)