I have a Python script that loads a Glade-GUI that can be translated. Everything works fine under Linux, but I am having a lot of trouble understanding the necessary steps on Windows.
All that seems necessary under Linux is:
import locale
[...]
locale.setlocale(locale.LC_ALL, locale.getlocale())
locale.bindtextdomain(APP_NAME, LOCALE_DIR)
[...]
class SomeClass():
self.builder = Gtk.Builder()
self.builder.set_translation_domain(APP_NAME)
locale.getlocale()
returns for example ('de_DE', 'UTF-8')
, the LOCALE_DIR
just points at the folder that has the compiled mo-files.
Under Windows this makes things more difficult:
locale.getlocale()
in the Python console returns (None, None)
and locale.getdefaultlocale()
returns ("de_DE", "cp1252")
. Furthermore when one tries to set locale.setlocale(locale.LC_ALL, "de_DE")
will spit out this error:
locale.setlocale(locale.LC_ALL, "de_DE")
File "C:\Python34\lib\locale.py", line 592, in setlocale
return _setlocale(category, locale)
locale.Error: unsupported locale setting
I leave it to the reader to speculate why Windows does not accept the most common language codes. So instead one is forced to use one of the below lines:
locale.setlocale(locale.LC_ALL, "deu_deu")
locale.setlocale(locale.LC_ALL, "german_germany")
Furthermore the locale
module on Windows does not have the bintextdomain
function. In order to use it one needs to import ctypes
:
import ctypes
libintl = ctypes.cdll.LoadLibrary("intl.dll")
libintl.bindtextdomain(APP_NAME, LOCALE_DIR)
libintl.bind_textdomain_codeset(APP_NAME, "UTF-8")
So my questions, apart from how this works, is:
- Which
intl.dll
do I need to include? (I tried thegnome/libintl-8.dll
from this source: http://sourceforge.net/projects/pygobjectwin32/, (pygi-aio-3.14.0_rev19-setup.exe)) - How can I check if the e.g. locale
deu_deu
gets the correct/mo/de/LC_MESSAGES/appname.mo/
?
Edit
My folder structure (Is it enough to have a de
folder? I tried using a deu_deu
folder but that did not help):
├── gnome_preamble.py
├── installer.cfg
├── pygibank
│ ├── __init__.py
│ ├── __main__.py
│ ├── mo
│ │ └── de
│ │ └── LC_MESSAGES
│ │ └── pygibank.mo
│ ├── po
│ │ ├── de.po
│ │ └── pygibank.pot
│ ├── pygibank.py
│ └── ui.glade
└── README.md
- I put the repository here: https://github.com/tobias47n9e/pygobject-locale
- And the compiled Windows installer (64 bit) is here: https://www.dropbox.com/s/qdd5q57ntaymfr4/pygibank_1.0.exe?dl=0
Short summary of the answer
The mo
-files should go into the gnome-packages in this way:
├── gnome
│ └── share
│ └── locale
│ └── de
| └── LC_MESSAGES
| └── pygibank.mo
You are close. This is a very complicated subject.
As I wrote in Question 10094335 and in Question 3678174:
To setup the locale to user current locale do not call:
locale.setlocale(locale.LC_ALL, locale.getlocale())
Simply call:
locale.setlocale(locale.LC_ALL, '')
As explained in Python setlocale
reference documentation.
This sets the locale for all categories to the user’s default setting (typically specified in the LANG environment variable).
Note that Windows doesn't have the LANG
environment variable set up, so, you need to do this before that line:
import sys
import os
import locale
if sys.platform.startswith('win'):
if os.getenv('LANG') is None:
lang, enc = locale.getdefaultlocale()
os.environ['LANG'] = lang
This will also make gettext to work for in-Python translations.
How this work you can check it in the source code here:
https://github.com/python/cpython/blob/master/Modules/_localemodule.c#L90
In particular, the error you're getting:
locale.Error: unsupported locale setting
Is expressed here:
https://github.com/python/cpython/blob/master/Modules/_localemodule.c#L112
Which is just a generic error message that the C call setlocale
failed with the given parameters.
The C call setlocale
is defined in the locale.h
header. In Linux, this is:
In Windows, this is the one used:
In Windows locale.h
documentation you can read:
The set of language and country/region strings supported by setlocale are listed in Language Strings and Country/Region Strings.
And that points to:
As you can see, for the 2010 version the setlocale
function expects the locale in the format you found out: deu_deu
, that differ from the one expected by the Linux version de_DE
. Your only option is to use a list of os-dependent locales to setup the locale. Very very sad indeed.
There is another issue here. If you change the version of the toolchain you can see that newer version of the setlocale
function now work more closelly to what Linux/POSIX does:
american english en-US
Visual Studio 2010 is the last release to support the old format, starting from version 2012 the new locale format is expected.
As you can imagine, the one you need to use depends on the version of the toolchain for which the CPython interpreter you're using was built to. I don't know which version are you using but according to the official Python Developer's Guide:
Python 3.5 and later use Microsoft Visual Studio 2015. [...] Python 3.3 and 3.4 use Microsoft Visual Studio 2010. [...] Most Python versions prior to 3.3 use Microsoft Visual Studio 2008. [...]
That is all related to the Python locale
module. Now, for the gettext
module or the gettext related functions in the locale
module, this is another C library called libintl
.
libintl
is what is called the C library that is part of gettext for all this translation magic:
One relevant part of this documentation says:
Note that on GNU systems, you don’t need to link with libintl because the gettext library functions are already contained in GNU libc.
But in Windows, because of the issues explained in Question 10094335 you need to load the libintl
library that is being used by PyGObject, that is, the very same that it was linked during build. That is done doing the steps you already wrote.
Which intl.dll do I need to include? (I tried the gnome/libintl-8.dll from this source: http://sourceforge.net/projects/pygobjectwin32/, (pygi-aio-3.14.0_rev19-setup.exe))
So, yes. The one that was used to link against when the pygobject AIO was build.
How can I check if the e.g. locale deu_deu gets the correct /mo/de/LC_MESSAGES/appname.mo/
Configure a few messages and note if they show translated. Just a note, is not a folder "/mo/de/LC_MESSAGES/appname.mo/"
, appname.mo
is a file.
Check my first answer to how to create the translation .po
file from the Glade file.
来源:https://stackoverflow.com/questions/32037573/load-gtk-glade-translations-in-windows-using-python-pygobject