#2512 implement the 3.0 gettext API

All the u* gettext variants were renamed to their
none u* variants, since there's no point in translating
to byte strings. I also killed off the unicode parameters
for install
This commit is contained in:
Benjamin Peterson 2008-07-14 14:32:15 +00:00
parent fbe94c55ca
commit 801844d6fc
4 changed files with 89 additions and 154 deletions

View File

@ -187,12 +187,11 @@ class can also install themselves in the built-in namespace as the function
:class:`NullTranslations` instance if *fallback* is true.
.. function:: install(domain[, localedir[, unicode [, codeset[, names]]]])
.. function:: install(domain[, localedir [, codeset[, names]]]])
This installs the function :func:`_` in Python's builtin namespace, based on
*domain*, *localedir*, and *codeset* which are passed to the function
:func:`translation`. The *unicode* flag is passed to the resulting translation
object's :meth:`install` method.
:func:`translation`.
For the *names* parameter, please see the description of the translation
object's :meth:`install` method.
@ -227,107 +226,91 @@ are the methods of :class:`NullTranslations`:
``None``.
.. method:: _parse(fp)
.. method:: NullTranslations._parse(fp)
No-op'd in the base class, this method takes file object *fp*, and reads
the data from the file, initializing its message catalog. If you have an
unsupported message catalog file format, you should override this method
to parse your format.
No-op'd in the base class, this method takes file object *fp*, and reads the
data from the file, initializing its message catalog. If you have an
unsupported message catalog file format, you should override this method to
parse your format.
.. method:: add_fallback(fallback)
.. method:: NullTranslations.add_fallback(fallback)
Add *fallback* as the fallback object for the current translation
object. A translation object should consult the fallback if it cannot provide a
translation for a given message.
Add *fallback* as the fallback object for the current translation object. A
translation object should consult the fallback if it cannot provide a
translation for a given message.
.. method:: gettext(message)
.. method:: NullTranslations.gettext(message)
If a fallback has been set, forward :meth:`gettext` to the
fallback. Otherwise, return the translated message. Overridden in derived
classes.
If a fallback has been set, forward :meth:`gettext` to the fallback. Otherwise,
return the translated message. Overridden in derived classes.
.. method:: lgettext(message)
.. method:: NullTranslations.lgettext(message)
If a fallback has been set, forward :meth:`lgettext` to the
fallback. Otherwise, return the translated message. Overridden in derived
classes.
.. method:: ugettext(message)
If a fallback has been set, forward :meth:`ugettext` to the
fallback. Otherwise, return the translated message as a string. Overridden
in derived classes.
If a fallback has been set, forward :meth:`lgettext` to the fallback. Otherwise,
return the translated message. Overridden in derived classes.
.. method:: ngettext(singular, plural, n)
.. method:: NullTranslations.ngettext(singular, plural, n)
If a fallback has been set, forward :meth:`ngettext` to the
fallback. Otherwise, return the translated message. Overridden in derived
classes.
.. method:: lngettext(singular, plural, n)
If a fallback has been set, forward :meth:`ngettext` to the
fallback. Otherwise, return the translated message. Overridden in derived
classes.
.. method:: ungettext(singular, plural, n)
If a fallback has been set, forward :meth:`ungettext` to the fallback.
Otherwise, return the translated message as a string. Overridden in
derived classes.
.. method:: info()
Return the "protected" :attr:`_info` variable.
If a fallback has been set, forward :meth:`ngettext` to the fallback. Otherwise,
return the translated message. Overridden in derived classes.
.. method:: charset()
.. method:: NullTranslations.lngettext(singular, plural, n)
Return the "protected" :attr:`_charset` variable.
If a fallback has been set, forward :meth:`ngettext` to the fallback. Otherwise,
return the translated message. Overridden in derived classes.
.. method:: output_charset()
.. method:: NullTranslations.info()
Return the "protected" :attr:`_output_charset` variable, which defines the
encoding used to return translated messages.
Return the "protected" :attr:`_info` variable.
.. method:: set_output_charset(charset)
.. method:: NullTranslations.charset()
Change the "protected" :attr:`_output_charset` variable, which defines the
encoding used to return translated messages.
Return the "protected" :attr:`_charset` variable.
.. method:: install([unicode [, names]])
.. method:: NullTranslations.output_charset()
If the *unicode* flag is false, this method installs :meth:`self.gettext`
into the built-in namespace, binding it to ``_``. If *unicode* is true,
it binds :meth:`self.ugettext` instead. By default, *unicode* is false.
Return the "protected" :attr:`_output_charset` variable, which defines the
encoding used to return translated messages.
If the *names* parameter is given, it must be a sequence containing the
names of functions you want to install in the builtin namespace in
addition to :func:`_`. Supported names are ``'gettext'`` (bound to
:meth:`self.gettext` or :meth:`self.ugettext` according to the *unicode*
flag), ``'ngettext'`` (bound to :meth:`self.ngettext` or
:meth:`self.ungettext` according to the *unicode* flag), ``'lgettext'``
and ``'lngettext'``.
Note that this is only one way, albeit the most convenient way, to make
the :func:`_` function available to your application. Because it affects
the entire application globally, and specifically the built-in namespace,
localized modules should never install :func:`_`. Instead, they should use
this code to make :func:`_` available to their module::
.. method:: NullTranslations.set_output_charset(charset)
import gettext
t = gettext.translation('mymodule', ...)
_ = t.gettext
Change the "protected" :attr:`_output_charset` variable, which defines the
encoding used to return translated messages.
This puts :func:`_` only in the module's global namespace and so only
affects calls within this module.
.. method:: NullTranslations.install([names])
this method installs :meth:`self.gettext` into the built-in namespace,
binding it to ``_``.
If the *names* parameter is given, it must be a sequence containing
the names of functions you want to install in the builtin namespace
in addition to :func:`_`. Supported names are ``'gettext'`` (bound
to :meth:`self.gettext`), ``'ngettext'`` (bound to
:meth:`self.ngettext`), ``'lgettext'`` and ``'lngettext'``.
Note that this is only one way, albeit the most convenient way, to
make the :func:`_` function available to your application. Because
it affects the entire application globally, and specifically the
built-in namespace, localized modules should never install
:func:`_`. Instead, they should use this code to make :func:`_`
available to their module::
import gettext
t = gettext.translation('mymodule', ...)
_ = t.gettext
This puts :func:`_` only in the module's global namespace and so only
affects calls within this module.
The :class:`GNUTranslations` class
@ -336,8 +319,7 @@ The :class:`GNUTranslations` class
The :mod:`gettext` module provides one additional class derived from
:class:`NullTranslations`: :class:`GNUTranslations`. This class overrides
:meth:`_parse` to enable reading GNU :program:`gettext` format :file:`.mo` files
in both big-endian and little-endian format. It also coerces both message ids
and message strings to Unicode.
in both big-endian and little-endian format.
:class:`GNUTranslations` parses optional meta-data out of the translation
catalog. It is convention with GNU :program:`gettext` to include meta-data as
@ -347,12 +329,7 @@ key ``Content-Type`` is found, then the ``charset`` property is used to
initialize the "protected" :attr:`_charset` instance variable, defaulting to
``None`` if not found. If the charset encoding is specified, then all message
ids and message strings read from the catalog are converted to Unicode using
this encoding. The :meth:`ugettext` method always returns a Unicode, while the
:meth:`gettext` returns an encoded bytestring. For the message id arguments
of both methods, either Unicode strings or bytestrings containing only
US-ASCII characters are acceptable. Note that the Unicode version of the
methods (i.e. :meth:`ugettext` and :meth:`ungettext`) are the recommended
interface to use for internationalized Python programs.
this encoding.
The entire set of key/value pairs are placed into a dictionary and set as the
"protected" :attr:`_info` instance variable.
@ -380,14 +357,6 @@ The following methods are overridden from the base class implementation:
:meth:`set_output_charset`.
.. method:: GNUTranslations.ugettext(message)
Look up the *message* id in the catalog and return the corresponding message
string, as a string. If there is no entry in the catalog for the
*message* id, and a fallback has been set, the look up is forwarded to the
fallback's :meth:`ugettext` method. Otherwise, the *message* id is returned.
.. method:: GNUTranslations.ngettext(singular, plural, n)
Do a plural-forms lookup of a message id. *singular* is used as the message id
@ -398,6 +367,15 @@ The following methods are overridden from the base class implementation:
If the message id is not found in the catalog, and a fallback is specified, the
request is forwarded to the fallback's :meth:`ngettext` method. Otherwise, when
*n* is 1 *singular* is returned, and *plural* is returned in all other cases.
Here is an example::
n = len(os.listdir('.'))
cat = GNUTranslations(somefile)
message = cat.ngettext(
'There is %(num)d file in this directory',
'There are %(num)d files in this directory',
n) % {'num': n}
.. method:: GNUTranslations.lngettext(singular, plural, n)
@ -407,27 +385,6 @@ The following methods are overridden from the base class implementation:
:meth:`set_output_charset`.
.. method:: GNUTranslations.ungettext(singular, plural, n)
Do a plural-forms lookup of a message id. *singular* is used as the message id
for purposes of lookup in the catalog, while *n* is used to determine which
plural form to use. The returned message string is a string.
If the message id is not found in the catalog, and a fallback is specified, the
request is forwarded to the fallback's :meth:`ungettext` method. Otherwise,
when *n* is 1 *singular* is returned, and *plural* is returned in all other
cases.
Here is an example::
n = len(os.listdir('.'))
cat = GNUTranslations(somefile)
message = cat.ungettext(
'There is %(num)d file in this directory',
'There are %(num)d files in this directory',
n) % {'num': n}
Solaris message catalog support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -538,13 +495,6 @@ module::
t = gettext.translation('spam', '/usr/share/locale')
_ = t.lgettext
If your translators were providing you with Unicode strings in their :file:`.po`
files, you'd instead do::
import gettext
t = gettext.translation('spam', '/usr/share/locale')
_ = t.ugettext
Localizing your application
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -560,11 +510,11 @@ driver file of your application::
import gettext
gettext.install('myapplication')
If you need to set the locale directory or the *unicode* flag, you can pass
these into the :func:`install` function::
If you need to set the locale directory, you can pass these into the
:func:`install` function::
import gettext
gettext.install('myapplication', '/usr/share/locale', unicode=1)
gettext.install('myapplication', '/usr/share/locale')
Changing languages on the fly

View File

@ -210,19 +210,6 @@ class NullTranslations:
else:
return msgid2
def ugettext(self, message):
if self._fallback:
return self._fallback.ugettext(message)
return str(message)
def ungettext(self, msgid1, msgid2, n):
if self._fallback:
return self._fallback.ungettext(msgid1, msgid2, n)
if n == 1:
return str(msgid1)
else:
return str(msgid2)
def info(self):
return self._info
@ -235,15 +222,14 @@ class NullTranslations:
def set_output_charset(self, charset):
self._output_charset = charset
def install(self, str=False, names=None):
def install(self, names=None):
import builtins
builtins.__dict__['_'] = str and self.ugettext or self.gettext
builtins.__dict__['_'] = self.gettext
if hasattr(names, "__contains__"):
if "gettext" in names:
builtins.__dict__['gettext'] = builtins.__dict__['_']
if "ngettext" in names:
builtins.__dict__['ngettext'] = (str and self.ungettext
or self.ngettext)
builtins.__dict__['ngettext'] = self.ngettext
if "lgettext" in names:
builtins.__dict__['lgettext'] = self.lgettext
if "lngettext" in names:
@ -367,31 +353,27 @@ class GNUTranslations(NullTranslations):
else:
return msgid2
def ugettext(self, message):
def gettext(self, message):
missing = object()
tmsg = self._catalog.get(message, missing)
if tmsg is missing:
if self._fallback:
return self._fallback.ugettext(message)
return self._fallback.gettext(message)
return str(message)
return tmsg
gettext = ugettext
def ungettext(self, msgid1, msgid2, n):
def ngettext(self, msgid1, msgid2, n):
try:
tmsg = self._catalog[(msgid1, self.plural(n))]
except KeyError:
if self._fallback:
return self._fallback.ungettext(msgid1, msgid2, n)
return self._fallback.ngettext(msgid1, msgid2, n)
if n == 1:
tmsg = str(msgid1)
else:
tmsg = str(msgid2)
return tmsg
ngettext = ungettext
# Locate a .mo file using the gettext strategy
def find(domain, localedir=None, languages=None, all=0):
@ -465,9 +447,9 @@ def translation(domain, localedir=None, languages=None,
return result
def install(domain, localedir=None, str=False, codeset=None, names=None):
def install(domain, localedir=None, codeset=None, names=None):
t = translation(domain, localedir, fallback=True, codeset=codeset)
t.install(str, names)
t.install(names)

View File

@ -143,13 +143,13 @@ trggrkg zrffntr pngnybt yvoenel.''')
t.install()
eq(_('nudge nudge'), 'wink wink')
# Try unicode return type
t.install(str=True)
t.install()
eq(_('mullusk'), 'bacon')
# Test installation of other methods
import builtins
t.install(str=True, names=["gettext", "lgettext"])
eq(_, t.ugettext)
eq(builtins.gettext, t.ugettext)
t.install(names=["gettext", "lgettext"])
eq(_, t.gettext)
eq(builtins.gettext, t.gettext)
eq(lgettext, t.lgettext)
del builtins.gettext
del builtins.lgettext
@ -305,7 +305,7 @@ class UnicodeTranslationsTest(GettextBaseTest):
self.t = gettext.GNUTranslations(fp)
finally:
fp.close()
self._ = self.t.ugettext
self._ = self.t.gettext
def test_unicode_msgid(self):
unless = self.failUnless

View File

@ -32,6 +32,9 @@ Library
code of every single module of the standard library, including invalid files
used in the test suite.
- All the u* variant functions and methods in gettext have been renamed to their
none u* siblings.
C API
-----