473,597 Members | 2,813 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Hello gettext


You'd think that using things like gettext would be easy. Superficially
it seems well documented in the Library Reference(*). However, it can
be surprisingly difficult to get the external details right.

* http://docs.python.org/lib/node738.html

Here's what I finally came up with as the simplest instructions, suitable
for an "overview of Python programming" class:

Start with the venerable "Hello, World!" program ... slightly modified
to make it ever-so-slightly more "functional :"

#!/usr/bin/env python
import sys

def hello(s="World" ):
print "Hello,", s

if __name__ == "__main__":
args = sys.argv[1:]
if len(args):
for each in args:
hello(each)
else:
hello()

... and add gettext support (and a little os.path handling on the
assumption that our message object files will not be readily
installable into the system /usr/share/locale tree):

#!/usr/bin/env python
import sys, os, gettext

_ = gettext.lgettex t
mydir = os.path.realpat h(os.path.dirna me(sys.argv[0]))
localedir = os.path.join(my dir, "locale")
gettext.bindtex tdomain('HelloP ython', localedir)
gettext.textdom ain('HelloPytho n')

def hello(s=_("Worl d")):
print _("Hello,"), s

if __name__ == "__main__":
args = sys.argv[1:]
if len(args):
for each in args:
hello(each)
else:
hello()

Note that I've only added five lines, the two modules to my import
line, and wrapped two strings with the conventional _() function.

This part is easy, and well-documented.

Running pygettext or GNU xgettext (-L or --language=Python ) is
also easy and gives us a file like:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS> , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-05-14 12:19+PDT\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS> \n"
"Language-Team: LANGUAGE <LL@li.org>\n "
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET \n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
#: HelloWorld.py:1 0
msgid "World"
msgstr ""

#: HelloWorld.py:1 1
msgid "Hello,"
msgstr ""

... I suppose I should add the appropriate magic package name,
version, author and other values to my source. Anyone remember
where those are documented? Does pygettext extract them from the
sources and insert them into the .pot?

Anyway, I minimally have to change one line thus:

"Content-Type: text/plain; charset=utf-8\n"

... and I suppose there are other ways to do this more properly.
(Documented where?)

I did find that I could either change that in the .pot file or
in the individual .po files. However, if I failed to change it
then my translations would NOT work and would throw an exception.

(Where is the setting to force the _() function to fail gracefully
--- falling back to no-translation and NEVER raise exceptions?
I seem to recall there is one somewhere --- but I just spent all
evening reading the docs and various Google hits to get this far; so
please excuse me if it's a blur right now).

Now we just copy these templates to individual .po files and
make our LC_MESSAGES directories:

mkdir locale && mv HelloPython.pot locale
cd locale

for i in es_ES fr_FR # ...
do
cp HelloPython.pot HelloPython_$i. po
mkdir -p $i/LC_MESSAGES
done

... and finally we can work on the translations.

We edit each of the _*.po files inserting "Hola" and "Bonjour" and
"Mundo" and "Monde" in the appropriate places. And then process
these into .mo files and move them into place as follows:

for i in *_*.po; do
i=${i#*_}
msgfmt -o ./${i%.po}/LC_MESSAGES/HelloPython.mo
done

... in other words HelloPython_es_ ES.po is written to
./es_ES/LC_MESSAGES/HelloPython.mo, etc.

This last part was the hardest to get right.

To test this we simply run:

$HELLO_PATH/HelloPython.py
Hello, World

export LANG=es_ES
$HELLO_PATH/HelloPython.py
Hola, Mundo

export LANG=fr_FR
$HELLO_PATH/HelloPython.py
Bonjour, Monde

export LANG=zh_ZH
$HELLO_PATH/HelloPython.py
Hello, World

... and we find that our Spanish and French translations work. (With
apologies if my translations are technically wrong).

Of course I realize this only barely scratches the surface of I18n and
L10n issues. Also I don't know, offhand, how much effort would be
required to make even this trivial example work on an MS Windows box.
It would be nice to find a document that would cover the topic in more
detail while still giving a sufficiently clear and concise set of examples
that one could follow them without getting hung up on something stupid
like: "Gee! You have to create $LANG/LC_MESSAGES/ directories and put
the .mo files thereunder; the Python won't find them under directly
under $LANG nor under LC_MESSAGES/$LANG" ... and "Gee! For reasons
I don't yet understand you need call both the .bindtextdomain () AND
the .textdomain() functions." ... and even "Hmmm ... seems that we
don't need to import locale and call local.setlocale () despite what
some examples in Google seem to suggest"(*)

* http://www.pixelbeat.org/programming/i18n.html

(So, when to you need that and when is gettext.install () really
useful?)

(I gather that the setlocale() stuff is not for simple string
translations but for things like numeric string formatting
with "%d" % ... for example).

--
Jim Dennis,
Starshine: Signed, Sealed, Delivered

May 14 '07 #1
1 3234
James T. Dennis <ja******@idiom .comwrote:

... just to follow-up my own posting --- as gauche as that is:
You'd think that using things like gettext would be easy. Superficially
it seems well documented in the Library Reference(*). However, it can
be surprisingly difficult to get the external details right.
* http://docs.python.org/lib/node738.html
Here's what I finally came up with as the simplest instructions, suitable
for an "overview of Python programming" class:
Start with the venerable "Hello, World!" program ... slightly modified
to make it ever-so-slightly more "functional :"

#!/usr/bin/env python
import sys
def hello(s="World" ):
print "Hello,", s
if __name__ == "__main__":
args = sys.argv[1:]
if len(args):
for each in args:
hello(each)
else:
hello()
... and add gettext support (and a little os.path handling on the
assumption that our message object files will not be readily
installable into the system /usr/share/locale tree):
#!/usr/bin/env python
import sys, os, gettext
_ = gettext.lgettex t
mydir = os.path.realpat h(os.path.dirna me(sys.argv[0]))
localedir = os.path.join(my dir, "locale")
gettext.bindtex tdomain('HelloP ython', localedir)
gettext.textdom ain('HelloPytho n')
def hello(s=_("Worl d")):
print _("Hello,"), s
Turns out this particular version is a Bad Idea(TM) if you ever
try to import this into another script and use it after changing
you os.environ['LANG'] value.

I mentioned in another message awhile back that I have an aversion
to using defaulted arguments other than by setting them as "None"
and I hesitated this time and then thought: "Oh, it's fine in this
case!"

Here's my updated version of this script:

-----------------------------------------------------------------------

#!/usr/bin/env python
import gettext, os, sys

_ = gettext.lgettex t
i18ndomain = 'HelloPython'
mydir = os.path.realpat h(os.path.dirna me(sys.argv[0]))
localedir = os.path.join(my dir, "locale")
gettext.install (i18ndomain, localedir=None, unicode=1)
gettext.bindtex tdomain(i18ndom ain, localedir)
gettext.textdom ain(i18ndomain)

def hello(s=None):
"""Print "Hello, World" (or its equivalent in any supported language):

Examples:
>>os.environ['LANG']=''
hello()
Hello, World
>>os.environ['LANG']='es_ES'
hello()
Hola, Mundo
>>os.environ['LANG']='fr_FR'
hello()
Bonjour, Monde

"""
if s is None:
s = _("World")
print _("Hello,"), s

def test():
import doctest
doctest.testmod ()

if __name__ == "__main__":
args = sys.argv[1:]
if 'PYDOCTEST' in os.environ and os.environ['PYDOCTEST']:
test()
elif len(args):
for each in args:
hello(each)
else:
hello()

-----------------------------------------------------------------------

... now with doctest support. :)
if __name__ == "__main__":
args = sys.argv[1:]
if len(args):
for each in args:
hello(each)
else:
hello()
Note that I've only added five lines, the two modules to my import
line, and wrapped two strings with the conventional _() function.
This part is easy, and well-documented.
Running pygettext or GNU xgettext (-L or --language=Python ) is
also easy and gives us a file like:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS> , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2007-05-14 12:19+PDT\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS> \n"
"Language-Team: LANGUAGE <LL@li.org>\n "
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET \n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"
#: HelloWorld.py:1 0
msgid "World"
msgstr ""
#: HelloWorld.py:1 1
msgid "Hello,"
msgstr ""
... I suppose I should add the appropriate magic package name,
version, author and other values to my source. Anyone remember
where those are documented? Does pygettext extract them from the
sources and insert them into the .pot?
Anyway, I minimally have to change one line thus:
"Content-Type: text/plain; charset=utf-8\n"
... and I suppose there are other ways to do this more properly.
(Documented where?)
I did find that I could either change that in the .pot file or
in the individual .po files. However, if I failed to change it
then my translations would NOT work and would throw an exception.
(Where is the setting to force the _() function to fail gracefully
--- falling back to no-translation and NEVER raise exceptions?
I seem to recall there is one somewhere --- but I just spent all
evening reading the docs and various Google hits to get this far; so
please excuse me if it's a blur right now).
Now we just copy these templates to individual .po files and
make our LC_MESSAGES directories:
mkdir locale && mv HelloPython.pot locale
cd locale
for i in es_ES fr_FR # ...
do
cp HelloPython.pot HelloPython_$i. po
mkdir -p $i/LC_MESSAGES
done
... and finally we can work on the translations.
We edit each of the _*.po files inserting "Hola" and "Bonjour" and
"Mundo" and "Monde" in the appropriate places. And then process
these into .mo files and move them into place as follows:
for i in *_*.po; do
i=${i#*_}
msgfmt -o ./${i%.po}/LC_MESSAGES/HelloPython.mo
done
... in other words HelloPython_es_ ES.po is written to
./es_ES/LC_MESSAGES/HelloPython.mo, etc.
This last part was the hardest to get right.
To test this we simply run:
$HELLO_PATH/HelloPython.py
Hello, World
export LANG=es_ES
$HELLO_PATH/HelloPython.py
Hola, Mundo
export LANG=fr_FR
$HELLO_PATH/HelloPython.py
Bonjour, Monde
export LANG=zh_ZH
$HELLO_PATH/HelloPython.py
Hello, World
... and we find that our Spanish and French translations work. (With
apologies if my translations are technically wrong).
Of course I realize this only barely scratches the surface of I18n and
L10n issues. Also I don't know, offhand, how much effort would be
required to make even this trivial example work on an MS Windows box.
It would be nice to find a document that would cover the topic in more
detail while still giving a sufficiently clear and concise set of examples
that one could follow them without getting hung up on something stupid
like: "Gee! You have to create $LANG/LC_MESSAGES/ directories and put
the .mo files thereunder; the Python won't find them under directly
under $LANG nor under LC_MESSAGES/$LANG" ... and "Gee! For reasons
I don't yet understand you need call both the .bindtextdomain () AND
the .textdomain() functions." ... and even "Hmmm ... seems that we
don't need to import locale and call local.setlocale () despite what
some examples in Google seem to suggest"(*)
* http://www.pixelbeat.org/programming/i18n.html
(So, when to you need that and when is gettext.install () really
useful?)
(I gather that the setlocale() stuff is not for simple string
translations but for things like numeric string formatting
with "%d" % ... for example).
--
Jim Dennis,
Starshine: Signed, Sealed, Delivered

May 15 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
2609
by: Pierre Rouleau | last post by:
I have a problem writing self-testable modules using doctest when these modules have internationalized strings using gettext _('...'). - The main module of an application (say app.py) calls gettext.install() to install the special _ function inside Python builtin. Other modules, taken from a general purpose collection of Python modules, also support internationalisation and doctest testing. For example:
1
2153
by: Terry Hancock | last post by:
I'm looking at the gettext module for the first time and learning how to write internationalized code in Python. Naturally, I also looked at the original Gnu gettext manual, which mentions that comments can be captured into the .po (.pot?) file for translators' benefit: /* Comment right before the gettext call, obviously in C */ printf(_("Apparently ambiguous string to translate"));
13
3934
by: cantabile | last post by:
Hi, I'm failing to make it work but can't find out what's wrong. Here's what I do : ================ test.py import gettext gettext.install('')
2
3514
by: Thomas W | last post by:
I'm trying to wrap my head around the docs at python.org related to the gettext-module, but I'm having some problem getting it to work. Is there any really simple, step-by-step on how to use this module available? This is my script so far : import gettext gettext.install('test2', '.', unicode=1) lang1 = gettext.translation('test2', languages=)
7
2785
by: russ.phillips.nospam | last post by:
Hi, I'm trying to use gettext to internationalise my project , but I'm getting the following error message with some translations: "Traceback (most recent call last): file PanicButton.py line 36 in ? file Gettext.pyc line 177 in _init_ file Gettext.pyc line 274 in _parse struct.error : unpack str size does not match format"
0
1284
by: redhog | last post by:
I can not get gettext to work at all under PHP. I run ubuntu 6.06.1 LTS, and the php5 package there announces that it supports gettext. Also, php -i sais gettext GetText Support =enabled, so it should be working. Here follows a minimal example that should be working, but isn't (gettext and msgfmt are the normal GNU gettext tools): $ cat foo.php #! /usr/bin/php <?php bindtextdomain($argv, $_ENV);
6
2020
by: =?iso-8859-1?B?QW5kcuk=?= | last post by:
I've encountered a problem using gettext with properties while using a Python interpreter. Here's a simple program that illustrate the problem. ============== # i18n_test.py: test of gettext & properties import gettext fr = gettext.translation('i18n_test', './translations',
2
4419
by: paolob | last post by:
Hi to all, I'm running php 5.2.5 on Debian etch, with apache 2.0.56. I need to include, in php.ini, gettext.so library but I didn't find anything. I've already install: apt-get install gettext apt-get install php-gettext apt-get install php5-cli apt-get install php5 php5-common
8
3375
by: howa | last post by:
http://hk2.php.net/manual/en/ref.gettext.php I just wonder why those kind of translation/mapping can't be implemented in using plain PHP array? Howard
0
7981
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, weíll explore What is ONU, What Is Router, ONU & Routerís main usage, and What is the difference between ONU and Router. Letís take a closer look ! Part I. Meaning of...
0
7894
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
8046
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8262
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
5847
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Duprť who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5437
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
3938
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2410
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
0
1245
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.