flufl.i18n-1.1.3/ 0000775 0001750 0001750 00000000000 12326554745 013701 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/MANIFEST.in 0000664 0001750 0001750 00000000143 12326544555 015433 0 ustar barry barry 0000000 0000000 include *.py MANIFEST.in
global-include *.txt *.rst *.po *.mo *.ini
exclude .bzrignore
prune build
flufl.i18n-1.1.3/setup.py 0000664 0001750 0001750 00000004301 12316276127 015403 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
from setup_helpers import (
description, get_version, long_description, require_python)
from setuptools import setup, find_packages
require_python(0x20600f0)
__version__ = get_version('flufl/i18n/__init__.py')
setup(
name='flufl.i18n',
version=__version__,
namespace_packages=['flufl'],
packages=find_packages(),
include_package_data=True,
zip_safe=False,
maintainer='Barry Warsaw',
maintainer_email='barry@python.org',
description=description('README.rst'),
long_description=long_description('README.rst', 'flufl/i18n/NEWS.rst'),
license='LGPLv3',
url='https://launchpad.net/flufl.i18n',
download_url='https://launchpad.net/flufl.i18n/+download',
test_suite='flufl.i18n.tests',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'License :: OSI Approved :: '
'GNU Lesser General Public License v3 or later (LGPLv3+)',
'Operating System :: POSIX',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS :: MacOS X',
'Programming Language :: Python',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Topic :: Software Development :: Internationalization',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: Localization',
]
)
flufl.i18n-1.1.3/setup.cfg 0000664 0001750 0001750 00000000221 12326554745 015515 0 ustar barry barry 0000000 0000000 [build_sphinx]
source_dir = flufl/i18n
[upload_docs]
upload_dir = build/sphinx/html
[egg_info]
tag_date = 0
tag_build =
tag_svn_revision = 0
flufl.i18n-1.1.3/setup_helpers.py 0000664 0001750 0001750 00000012042 12316276127 017126 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""setup.py helper functions."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'description',
'find_doctests',
'get_version',
'long_description',
'require_python',
]
import os
import re
import sys
DEFAULT_VERSION_RE = re.compile(r'(?P\d+\.\d+(?:\.\d+)?)')
EMPTYSTRING = ''
__version__ = '2.1'
def require_python(minimum):
"""Require at least a minimum Python version.
The version number is expressed in terms of `sys.hexversion`. E.g. to
require a minimum of Python 2.6, use::
>>> require_python(0x206000f0)
:param minimum: Minimum Python version supported.
:type minimum: integer
"""
if sys.hexversion < minimum:
hversion = hex(minimum)[2:]
if len(hversion) % 2 != 0:
hversion = '0' + hversion
split = list(hversion)
parts = []
while split:
parts.append(int(''.join((split.pop(0), split.pop(0))), 16))
major, minor, micro, release = parts
if release == 0xf0:
print('Python {0}.{1}.{2} or better is required'.format(
major, minor, micro))
else:
print('Python {0}.{1}.{2} ({3}) or better is required'.format(
major, minor, micro, hex(release)[2:]))
sys.exit(1)
def get_version(filename, pattern=None):
"""Extract the __version__ from a file without importing it.
While you could get the __version__ by importing the module, the very act
of importing can cause unintended consequences. For example, Distribute's
automatic 2to3 support will break. Instead, this searches the file for a
line that starts with __version__, and extract the version number by
regular expression matching.
By default, two or three dot-separated digits are recognized, but by
passing a pattern parameter, you can recognize just about anything. Use
the `version` group name to specify the match group.
:param filename: The name of the file to search.
:type filename: string
:param pattern: Optional alternative regular expression pattern to use.
:type pattern: string
:return: The version that was extracted.
:rtype: string
"""
if pattern is None:
cre = DEFAULT_VERSION_RE
else:
cre = re.compile(pattern)
with open(filename) as fp:
for line in fp:
if line.startswith('__version__'):
mo = cre.search(line)
assert mo, 'No valid __version__ string found'
return mo.group('version')
raise AssertionError('No __version__ assignment found')
def find_doctests(start='.', extension='.rst'):
"""Find separate-file doctests in the package.
This is useful for Distribute's automatic 2to3 conversion support. The
`setup()` keyword argument `convert_2to3_doctests` requires file names,
which may be difficult to track automatically as you add new doctests.
:param start: Directory to start searching in (default is cwd)
:type start: string
:param extension: Doctest file extension (default is .txt)
:type extension: string
:return: The doctest files found.
:rtype: list
"""
doctests = []
for dirpath, dirnames, filenames in os.walk(start):
doctests.extend(os.path.join(dirpath, filename)
for filename in filenames
if filename.endswith(extension))
return doctests
def long_description(*filenames):
"""Provide a long description."""
res = ['']
for filename in filenames:
with open(filename) as fp:
for line in fp:
res.append(' ' + line)
res.append('')
res.append('\n')
return EMPTYSTRING.join(res)
def description(filename):
"""Provide a short description."""
# This ends up in the Summary header for PKG-INFO and it should be a
# one-liner. It will get rendered on the package page just below the
# package version header but above the long_description, which ironically
# gets stuff into the Description header. It should not include reST, so
# pick out the first single line after the double header.
with open(filename) as fp:
for lineno, line in enumerate(fp):
if lineno < 3:
continue
line = line.strip()
if len(line) > 0:
return line
flufl.i18n-1.1.3/flufl/ 0000775 0001750 0001750 00000000000 12326554745 015011 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/__init__.py 0000664 0001750 0001750 00000001566 12316276127 017124 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n.
#
# flufl.i18n is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
# this is a namespace package
try:
import pkg_resources
pkg_resources.declare_namespace(__name__)
except ImportError:
import pkgutil
__path__ = pkgutil.extend_path(__path__, __name__)
flufl.i18n-1.1.3/flufl/i18n/ 0000775 0001750 0001750 00000000000 12326554745 015570 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/_registry.py 0000664 0001750 0001750 00000003166 12316276127 020151 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Translation registry."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'registry',
]
from flufl.i18n._application import Application
class Registry:
"""A registry of application translation lookup strategies."""
def __init__(self):
# Map application names to Application instances.
self._registry = {}
def register(self, strategy):
"""Add an association between an application and a lookup strategy.
:param strategy: An application translation lookup strategy.
:type application: A callable object with a .name attribute
:return: An application instance which can be used to access the
language catalogs for the application.
:rtype: `Application`
"""
application = Application(strategy)
self._registry[strategy.name] = application
return application
registry = Registry()
flufl.i18n-1.1.3/flufl/i18n/docs/ 0000775 0001750 0001750 00000000000 12326554745 016520 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/docs/using.rst 0000664 0001750 0001750 00000016356 12316276127 020404 0 ustar barry barry 0000000 0000000 ============================
Using the flufl.i18n library
============================
Set up
======
There are two basic ways that your application can set up translations using
this library. The simple initialization will work for most applications,
where there is only one language context for the entire run of the
application. The more complex initialization works well for applications like
servers that may want to use multiple language contexts during their
execution.
Single language contexts
------------------------
If your application only needs one language context for its entire execution,
you can use the simple API to set things up.
>>> from flufl.i18n import initialize
The library by default uses the ``$LANG`` and ``$LOCPATH`` environment
variables to set things up::
>>> # The testing 'xx' language rot13's the source string. The
>>> # gettext catalogs are in this package directory.
>>> import os
>>> import flufl.i18n.testing.messages
>>> os.environ['LANG'] = 'xx'
>>> os.environ['LOCPATH'] = os.path.dirname(
... flufl.i18n.testing.messages.__file__)
Now you just need to call the ``initialize()`` function with the application's
name and you'll get an object back that you can assign to the ``_()`` function
for run-time translations.
>>> _ = initialize('flufl')
>>> print(_('A test message'))
N grfg zrffntr
It's probably best to just share this function through imports, but it does no
harm to call ``initialize()`` again.
>>> _ = initialize('flufl')
>>> print(_('A test message'))
N grfg zrffntr
..
>>> # Unregister the application domain used earlier. Also, clear the
>>> # environment settings from above.
>>> from flufl.i18n import registry
>>> registry._registry.clear()
>>> del os.environ['LANG']
>>> del os.environ['LOCPATH']
Multiple language contexts
--------------------------
Some applications, such as servers, are more complex; they need multiple
language contexts during their execution. To support this, there is a global
registry of catalog look up :doc:`strategies `. When a particular
language code is specified, the strategy is used to find the catalog that
provides that language's translations.
``flufl.i18n`` comes with a couple of fairly simple strategies, but you can of
course write your own. A convenient built-in strategy looks up catalogs from
within the package directory using `GNU gettext`_'s convention, where the base
directory for the catalogs is rooted in a subpackage.
>>> from flufl.i18n import registry
>>> from flufl.i18n import PackageStrategy
>>> strategy = PackageStrategy('flufl', flufl.i18n.testing.messages)
The first argument is the application name, which must be unique among all
registered strategies. The second argument is the package where the
translations can be found.
Once you have the desired strategy, register this with the global registry.
The registration process returns an application object which can be used to
look up language codes.
>>> application = registry.register(strategy)
The application object keeps track of a current translation catalog, and
exports a method which you can bind to the *underscore* function in your
module globals for convenient gettext usage. By doing so, at run time,
``_()`` will always translate the string argument to the current catalog's
language.
>>> _ = application._
By default the application just translates the source string back into the
source string. I.e. it is a null translator.
>>> print(_('A test message'))
A test message
And it has no language code.
>>> print(_.code)
None
You can temporarily push a new language context to the top of the stack, which
automatically rebinds the underscore function to the language's catalog.
>>> _.push('xx')
>>> print(_.code)
xx
>>> print(_('A test message'))
N grfg zrffntr
Pop the current language to return to the default. Once you're at the bottom
of the stack, more pops will just give you the default translation.
>>> _.pop()
>>> print(_.code)
None
>>> print(_('A test message'))
A test message
>>> _.pop()
>>> print(_.code)
None
>>> print(_('A test message'))
A test message
The underscore method has a context manager called ``using`` which can be used
to temporarily set a new language inside a ``with`` statement::
>>> with _.using('xx'):
... print(_('A test message'))
N grfg zrffntr
>>> print(_('A test message'))
A test message
These ``with`` statements are nestable::
>>> with _.using('xx'):
... print(_('A test message'))
... with _.using('yy'):
... print(_('A test message'))
... print(_('A test message'))
N grfg zrffntr
egassem tset A
N grfg zrffntr
>>> print(_('A test message'))
A test message
You can set the bottom language context, which replaces the default null
translation::
>>> _.default = 'xx'
>>> print(_('A test message'))
N grfg zrffntr
>>> _.pop()
>>> print(_.code)
xx
>>> print(_('A test message'))
N grfg zrffntr
>>> with _.using('yy'):
... print(_('A test message'))
egassem tset A
>>> print(_('A test message'))
N grfg zrffntr
Substitutions and placeholders
==============================
As you can see from the example above, using the library is very simple. You
just put the string to translate inside the underscore function. What if your
source strings need placeholders for other runtime information?
In that case, you use `PEP 292`_ style substitution strings as arguments to
the underscore function. Substitutions are taken from the locals and globals
of the function doing the translation, so that you don't have to repeat
yourself.
>>> ordinal = 'first'
>>> def print_it(name):
... print(_('The $ordinal test message $name'))
In this example, when ``print_it()`` is called, the ``$ordinal`` placeholder
is taken from globals, while the ``$name`` placeholder is taken from the
function locals (i.e. the arguments).
..
>>> # Reset the language context.
>>> del _.default
>>> print(_.code)
None
With no language context in place, the source string is printed unchanged,
except that the substitutions are made.
>>> print_it('Anne')
The first test message Anne
When a substitution is missing, rather than raise an exception, the
``$variable`` is used unchanged.
>>> del ordinal
>>> print_it('Bart')
The $ordinal test message Bart
When there is a language context in effect, the substitutions happen after
translation.
>>> ordinal = 'second'
>>> with _.using('xx'):
... print_it('Cris')
second si n grfg zrffntr Cris
Some languages change the order of the substitution variables, but of course
there is no problem with that.
>>> ordinal = 'third'
>>> with _.using('yy'):
... print_it('Dave')
Dave egassem tset third eht
Locals always take precedence over globals::
>>> def print_it(name, ordinal):
... print(_('The $ordinal test message $name'))
>>> with _.using('yy'):
... print_it('Elle', 'fourth')
Elle egassem tset fourth eht
.. _`GNU gettext`: http://www.gnu.org/software/gettext/manual/gettext.html
.. _`PEP 292`: http://www.python.org/dev/peps/pep-0292/
flufl.i18n-1.1.3/flufl/i18n/docs/__init__.py 0000664 0001750 0001750 00000000000 12316276127 020611 0 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/docs/expand.rst 0000664 0001750 0001750 00000001434 12316276127 020525 0 ustar barry barry 0000000 0000000 ===================
Expanding templates
===================
`PEP 292`_ defines a simplified string template, where substitution variables
are identified by a leading ``$``-sign. The substitution dictionary names the
keys and values that should be interpolated into the template::
>>> key_1 = 'key_1'
>>> key_2 = 'key_2'
>>> from flufl.i18n import expand
>>> # This may fail for Python < 2.6.5
>>> print(expand(
... '$key_2 is different than $key_1', {
... key_1: 'the first key',
... key_2: 'the second key',
... }))
the second key is different than the first key
See `issue 4978`_ for Python 2.6.x compatibility.
.. _`PEP 292`: http://www.python.org/dev/peps/pep-0292/
.. _`issue 4978`: http://bugs.python.org/issue4978
flufl.i18n-1.1.3/flufl/i18n/docs/strategies.rst 0000664 0001750 0001750 00000006117 12316276127 021423 0 ustar barry barry 0000000 0000000 ==================
Catalog strategies
==================
The way ``flufl.i18n`` finds its catalog for an application is extensible.
These are called *strategies*. ``flufl.i18n`` comes with a couple of fairly
simple strategies. The first locates catalog files from within a package's
directory. Inside the package directory, you still need the ``gettext``
standard layout of ``/LC_MESSAGES/.mo``.
Python package strategies
=========================
For example, to use the catalog in ``flufl.i18n``'s testing package, you would
use the ``PackageStrategy``.
>>> from flufl.i18n import PackageStrategy
>>> import flufl.i18n.testing.messages
By setting the ``$LANG`` environment variable, we can specify that the
application translates into that language automatically.
>>> # The testing 'xx' language rot13's the source string.
>>> import os
>>> os.environ['LANG'] = 'xx'
The first argument is the application name, which must be unique among all
registered strategies. The second argument is the package in which to search.
>>> strategy = PackageStrategy('flufl', flufl.i18n.testing.messages)
Once you have the desired strategy, register this with the global registry.
The registration process returns an application object which can be used to
look up language codes.
>>> from flufl.i18n import registry
>>> application = registry.register(strategy)
The application object keeps track of a current translation catalog, and
exports a method which you can bind to the 'underscore' function in your
module globals for convenient gettext usage.
>>> _ = application._
By doing so, at run time, ``_()`` will always translate the string argument to
the current catalog's language.
>>> print(_('A test message'))
N grfg zrffntr
..
>>> # Hack to unregister the previous strategy.
>>> registry._registry.clear()
Simple strategy
===============
There is also a simpler strategy that uses both the ``$LANG`` environment
variable, and the ``$LOCPATH`` environment variable to set things up::
>>> os.environ['LOCPATH'] = os.path.dirname(
... flufl.i18n.testing.messages.__file__)
>>> from flufl.i18n import SimpleStrategy
>>> strategy = SimpleStrategy('flufl')
>>> application = registry.register(strategy)
>>> _ = application._
>>> print(_('A test message'))
N grfg zrffntr
Calling with zero arguments
===========================
Strategies should be prepared to accept zero arguments when called, to produce
a *default* translation (usually the ``gettext.NullTranslator``). Here, we
look for the `ugettext()` method for Python 2 and the `gettext()` method for
Python 3::
>>> def get_ugettext(strategy):
... catalog = strategy()
... try:
... return catalog.ugettext
... except AttributeError:
... # Python 3
... return catalog.gettext
>>> print(get_ugettext(SimpleStrategy('example'))('A test message'))
A test message
>>> print(get_ugettext(PackageStrategy(
... 'example', flufl.i18n.testing.messages))('A test message'))
A test message
flufl.i18n-1.1.3/flufl/i18n/testing/ 0000775 0001750 0001750 00000000000 12326554745 017245 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/ 0000775 0001750 0001750 00000000000 12326554745 021054 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/__init__.py 0000664 0001750 0001750 00000000000 12316276127 023145 0 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/xx/ 0000775 0001750 0001750 00000000000 12326554745 021513 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/xx/LC_MESSAGES/ 0000775 0001750 0001750 00000000000 12326554745 023300 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/xx/LC_MESSAGES/flufl.mo 0000664 0001750 0001750 00000000772 11624413310 024731 0 ustar barry barry 0000000 0000000 4 L ` a p 9 A test message The $ordinal test message $name Project-Id-Version: PACKAGE VERSION
POT-Creation-Date: Sun Jan 8 15:53:47 2006
PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
Last-Translator: FULL NAME
Language-Team: LANGUAGE
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Generated-By: hand
N grfg zrffntr $ordinal si n grfg zrffntr $name flufl.i18n-1.1.3/flufl/i18n/testing/messages/xx/LC_MESSAGES/flufl.po 0000664 0001750 0001750 00000001247 12316276127 024746 0 ustar barry barry 0000000 0000000 # A testing catalog
# Copyright (C) 2009-2014 by Barry A. Warsaw
# Barry Warsaw , 2009, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: Sun Jan 8 15:53:47 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: hand\n"
#: flufl/i18n/docs/readme.txt:39
msgid "A test message"
msgstr "N grfg zrffntr"
#: flufl/i18n/docs/readme.txt:40
msgid "The $ordinal test message $name"
msgstr "$ordinal si n grfg zrffntr $name"
flufl.i18n-1.1.3/flufl/i18n/testing/messages/yy/ 0000775 0001750 0001750 00000000000 12326554745 021515 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/yy/LC_MESSAGES/ 0000775 0001750 0001750 00000000000 12326554745 023302 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/testing/messages/yy/LC_MESSAGES/flufl.mo 0000664 0001750 0001750 00000000771 11624413325 024740 0 ustar barry barry 0000000 0000000 4 L ` a p 9 A test message The $ordinal test message $name Project-Id-Version: PACKAGE VERSION
POT-Creation-Date: Sun Jan 8 15:53:47 2006
PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE
Last-Translator: FULL NAME
Language-Team: LANGUAGE
MIME-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit
Generated-By: hand
egassem tset A $name egassem tset $ordinal eht flufl.i18n-1.1.3/flufl/i18n/testing/messages/yy/LC_MESSAGES/flufl.po 0000664 0001750 0001750 00000001246 12316276127 024747 0 ustar barry barry 0000000 0000000 # A testing catalog
# Copyright (C) 2009-2014 by Barry A. Warsaw
# Barry Warsaw , 2009, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: Sun Jan 8 15:53:47 2006\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: hand\n"
#: flufl/i18n/docs/readme.txt:39
msgid "A test message"
msgstr "egassem tset A"
#: flufl/i18n/docs/readme.txt:40
msgid "The $ordinal test message $name"
msgstr "$name egassem tset $ordinal eht"
flufl.i18n-1.1.3/flufl/i18n/testing/__init__.py 0000664 0001750 0001750 00000000000 12316276127 021336 0 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/_strategy.py 0000664 0001750 0001750 00000006102 12316276127 020134 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Catalog search strategies."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'PackageStrategy',
'SimpleStrategy',
]
import os
import gettext
class _BaseStrategy:
"""Common code for strategies."""
def __init__(self, name):
"""Create a catalog lookup strategy.
:param name: The application's name.
:type name: string
"""
self.name = name
self._messages_dir = None
def __call__(self, language_code=None):
"""Find the catalog for the language.
:param language_code: The language code to find. If None, then the
default gettext language code lookup scheme is used.
:type language_code: string
:return: A `gettext` catalog.
:rtype: `gettext.NullTranslations` or subclass
"""
# gettext.translation() requires None or a sequence.
languages = (None if language_code is None else [language_code])
try:
return gettext.translation(
self.name, self._messages_dir, languages)
except IOError:
# Fall back to untranslated source language.
return gettext.NullTranslations()
class PackageStrategy(_BaseStrategy):
"""A strategy that finds catalogs based on package paths."""
def __init__(self, name, package):
"""Create a catalog lookup strategy.
:param name: The application's name.
:type name: string
:param package: The package path to the message catalogs. This
strategy uses the __file__ of the package path as the directory
containing `gettext` messages.
:type package_name: module
"""
super(PackageStrategy, self).__init__(name)
self._messages_dir = os.path.dirname(package.__file__)
class SimpleStrategy(_BaseStrategy):
"""A simpler strategy for getting translations."""
def __init__(self, name):
"""Create a catalog lookup strategy.
:param name: The application's name.
:type name: string
:param package: The package path to the message catalogs. This
strategy uses the __file__ of the package path as the directory
containing `gettext` messages.
:type package_name: module
"""
super(SimpleStrategy, self).__init__(name)
self._messages_dir = os.environ.get('LOCPATH')
flufl.i18n-1.1.3/flufl/i18n/_application.py 0000664 0001750 0001750 00000020520 12316276127 020575 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""An application."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'Application',
]
from flufl.i18n._translator import Translator
class _Using:
"""Context manager for _.using()."""
def __init__(self, application, language_code):
self._application = application
self._language_code = language_code
def __enter__(self):
self._application.push(self._language_code)
def __exit__(self, *exc_info):
self._application.pop()
# Do not suppress exceptions.
return False
class _Underscore:
"""The implementation of the _() function.
This class is internal representation only and has an incestuous
relationship with the Application class.
"""
def __init__(self, application):
self._application = application
def __call__(self, original, extras=None):
"""Translate the string into the language of the current context.
:param original: The original string to translate.
:type original: string
:param extras: Extra substitution mapping, elements of which override
the locals and globals.
:return: The translated string.
:rtype: string
"""
return self._application.current.translate(original, extras)
def using(self, language_code):
"""Create a context manager for temporary translation.
While in this context manager, translations use the given language
code. When the with statement exits, the original language is
restored. These are nestable.
"""
return _Using(self._application, language_code)
def push(self, language_code):
"""Push a new catalog onto the stack.
The translation catalog associated with the language code now becomes
the currently active translation context.
"""
self._application.push(language_code)
def pop(self):
"""Pop the current catalog off the translation stack.
No exception is raised for under-runs. In that case, pop() just
no-ops and the null translation becomes the current translation
context.
"""
self._application.pop()
@property
def default(self):
"""Return the default language code.
:return: The default language code.
:rtype: string or None if there is no default language
"""
return self._application.default
@default.setter
def default(self, language_code):
"""Set the default language code.
:param language_code: The language code for the default translator.
:type language_code: string
"""
self._application.default = language_code
@default.deleter
def default(self):
"""Reset the default language to the null translator."""
del self._application.default
@property
def code(self):
"""Return the language code currently in effect."""
code = self._application.code
if code is None:
return self.default
return code
class Application:
"""Manage all the catalogs for a particular application.
You can ask the application for a specific catalog based on the language
code. The Application requires a strategy for finding catalog files.
Attributes:
* dedent (default True) - controls whether translated strings are dedented
or not. This is passed through to the underlying `Translator`
instance.
* depth (default 2) - The number of stack frames to call sys._getframe()
with in the underlying `Translator` instance. Passed through to that
class's constructor.
"""
def __init__(self, strategy):
"""Create an `Application`.
Use the `dedent` attribute on this instance to control whether
translated strings are dedented or not. This is passed straight
through to the `Translator` instance created in the _() method.
:param strategy: A callable that can find catalog files for the
application based on the language code.
:type strategy: callable taking one string argument, the language code.
"""
self._strategy = strategy
# A mapping from language codes to catalogs.
self._catalogs = {}
self._stack = []
# Arguments to the Translator constructor.
self.dedent = True
self.depth = 2
# By default, the baseline translator is the null translator. Use our
# public API so that we share code.
self._default_language = None
self._default_translator = None
# This sets the _default_translator.
del self.default
@property
def name(self):
"""The application name.
:return: The application name.
:rtype: string
"""
return self._strategy.name
@property
def default(self):
"""Return the default language code.
:return: The default language code.
:rtype: string or None if there is no default language
"""
return self._default_language
@default.setter
def default(self, language_code):
"""Set the default language code.
:param language_code: The language code for the default translator.
:type language_code: string
"""
self._default_language = language_code
catalog = self.get(language_code)
self._default_translator = Translator(catalog, self.dedent, self.depth)
@default.deleter
def default(self):
"""Reset the default language to the null translator."""
self._default_language = None
self._default_translator = Translator(
self._strategy(), self.dedent, self.depth)
def get(self, language_code):
"""Get the catalog associated with the language code.
:param language_code: The language code.
:type language_code: string
:return: A `gettext` catalog.
:rtype: `gettext.NullTranslations` or subclass.
"""
missing = object()
catalog = self._catalogs.get(language_code, missing)
if catalog is missing:
catalog = self._strategy(language_code)
self._catalogs[language_code] = catalog
return catalog
@property
def _(self):
"""Return a translator object, tied to the current catalog.
:return: A translator context object for the current active catalog.
:rtype: `Translator`
"""
return _Underscore(self)
def push(self, language_code):
"""Push a new catalog onto the stack.
The translation catalog associated with the language code now becomes
the currently active translation context.
"""
catalog = self.get(language_code)
translator = Translator(catalog, self.dedent, self.depth)
self._stack.append((language_code, translator))
def pop(self):
"""Pop the current catalog off the translation stack.
No exception is raised for under-runs. In that case, pop() just
no-ops and the null translation becomes the current translation
context.
"""
if len(self._stack) > 0:
self._stack.pop()
@property
def current(self):
"""Return the current translator.
:return: The current translator.
:rtype: `Translator`
"""
if len(self._stack) == 0:
return self._default_translator
return self._stack[-1][1]
@property
def code(self):
"""Return the current language code.
:return: The current language code.
:rtype: string
"""
if len(self._stack) == 0:
return None
return self._stack[-1][0]
flufl.i18n-1.1.3/flufl/i18n/NEWS.rst 0000664 0001750 0001750 00000003776 12326543735 017110 0 ustar barry barry 0000000 0000000 =====================
NEWS for flufl.i18n
=====================
1.1.3 (2014-04-25)
==================
* Include MANIFEST.in in the sdist tarball, otherwise the Debian package
won't built correctly.
1.1.2 (2014-03-31)
==================
* Fix documentation bug. LP: #1026403
* Use modern setuptools rather than distutils.
* Bump copyright years.
1.1.1 (2012-04-19)
==================
* Add classifiers to setup.py and make the long description more compatible
with the Cheeseshop.
* Other changes to make the Cheeseshop page look nicer. (LP: #680136)
* setup_helper.py version 2.1.
1.1 (2012-01-19)
================
* Support Python 3 without the need for 2to3.
1.0.4 (2010-12-06)
==================
* Restore missing line from MANIFEST.in to fix distribution tarball.
1.0.3 (2010-12-01)
==================
* Fix setup.py to not install myfixers artifact directory on install.
* Remove pylint.rc; we'll use pyflakes instead.
1.0.2 (2010-06-23)
==================
* Small documentation fix.
1.0.1 (2010-06-09)
==================
* Ditch the use of zc.buildout.
* Improved documentation.
1.0 (2010-04-24)
================
* Use Distribute instead of Setuptools.
* Port to Python 3 when used with 2to3.
* More documentation improvements.
0.6 (2010-04-21)
================
* Documentation and lint clean up.
0.5 (2010-04-20)
================
* Added a simplified initialization API for one-language-context
applications. This works much better for non-server applications.
* Added a SimpleStrategy which recognizes the $LOCPATH environment variable.
* Show how PEP 292 strings are supported automatically.
* When strategies are called with zero arguments, they supply the default
translation context, which is usually a NullTranslation. This is better
than hardcoding the NullTranslation in the Application.
0.4 (2010-03-04)
================
* Add the ability to get the current language code, via _.code
0.3 (2009-11-15)
================
* Initial release; refactored from Mailman 3.
flufl.i18n-1.1.3/flufl/i18n/__init__.py 0000664 0001750 0001750 00000002176 12326544030 017671 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Expose sub-module names in the package namespace."""
__version__ = '1.1.3'
from flufl.i18n._expand import expand
from flufl.i18n._registry import registry
from flufl.i18n._strategy import *
def initialize(domain):
"""A convenience function for setting up translation.
:param domain: The application's name.
:type domain: string
"""
strategy = SimpleStrategy(domain)
application = registry.register(strategy)
return application._
flufl.i18n-1.1.3/flufl/i18n/conf.py 0000664 0001750 0001750 00000015331 12316276230 017057 0 ustar barry barry 0000000 0000000 # -*- coding: utf-8 -*-
#
# flufl.i18n documentation build configuration file, created by
# sphinx-quickstart on Fri Apr 23 11:41:37 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
from __future__ import print_function
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['../../_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'README'
# General information about the project.
project = 'flufl.i18n'
copyright = '2009-2014, Barry A. Warsaw'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
from flufl.i18n import __version__
# The short X.Y version.
version = __version__
# The full version, including alpha/beta/rc tags.
release = __version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build', 'build', 'flufl.i18n.egg-info', 'distribute-0.6.10']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# " v documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['../../_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'flufli18ndoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('README.rst', 'flufli18n.tex', 'flufl.i18n Documentation',
'Barry A. Warsaw', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
import errno
def index_html():
cwd = os.getcwd()
try:
os.chdir('build/sphinx/html')
try:
os.symlink('README.html', 'index.html')
except OSError as error:
if error.errno != errno.EEXIST:
raise
print('index.html -> README.html')
finally:
os.chdir(cwd)
import atexit
atexit.register(index_html)
flufl.i18n-1.1.3/flufl/i18n/_expand.py 0000664 0001750 0001750 00000003044 12316276127 017553 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""String interpolation."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'expand',
]
import logging
from string import Template
log = logging.getLogger('flufl.i18n')
def expand(template, substitutions, template_class=Template):
"""Expand string template with substitutions.
:param template: A PEP 292 $-string template.
:type template: string
:param substitutions: The substitutions dictionary.
:type substitutions: dict
:param template_class: The template class to use.
:type template_class: class
:return: The substituted string.
:rtype: string
"""
try:
return template_class(template).safe_substitute(substitutions)
except (TypeError, ValueError):
# The template is really screwed up.
log.exception('broken template: %s', template)
flufl.i18n-1.1.3/flufl/i18n/_substitute.py 0000664 0001750 0001750 00000002514 12316276127 020510 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Substitutions."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'Template',
'attrdict',
]
import string
_missing = object()
class Template(string.Template):
"""Match any attribute path."""
idpattern = r'[_a-z][_a-z0-9.]*'
class attrdict(dict):
"""Follow attribute paths."""
def __getitem__(self, key):
parts = key.split('.')
value = super(attrdict, self).__getitem__(parts.pop(0))
while parts:
value = getattr(value, parts.pop(0), _missing)
if value is _missing:
raise KeyError(key)
return value
flufl.i18n-1.1.3/flufl/i18n/README.rst 0000664 0001750 0001750 00000005425 12316276247 017262 0 ustar barry barry 0000000 0000000 ======================================================
flufl.i18n - A high level API for internationalization
======================================================
This package provides a high level, convenient API for managing
internationalization translation contexts in Python application. There is a
simple API for single-context applications, such as command line scripts which
only need to translate into one language during the entire course of their
execution. There is a more flexible, but still convenient API for
multi-context applications, such as servers, which may need to switch language
contexts for different tasks.
Requirements
============
``flufl.i18n`` requires Python 2.6.5 or newer, and is compatible with Python 3.
Documentation
=============
A `simple guide`_ to using the library is available within this package, in
the form of doctests. The manual is also available online in the Cheeseshop
at:
http://packages.python.org/flufl.i18n
Project details
===============
The project home page is:
http://launchpad.net/flufl.i18n
You should report bugs at:
http://bugs.launchpad.net/flufl.i18n
You can download the latest version of the package either from the Cheeseshop:
http://pypi.python.org/pypi/flufl.i18n
or from the Launchpad page above. Of course you can also just install it with
``pip`` or ``easy_install`` from the command line::
% sudo pip install flufl.i18n
% sudo easy_install flufl.i18n
You may want to use `virtualenv`_ instead of installing the package into the
system Python.
You can grab the latest development copy of the code using Bazaar, from the
Launchpad home page above. See http://bazaar-vcs.org for details on the
Bazaar distributed revision control system. If you have Bazaar installed, you
can branch the code like this::
% bzr branch lp:flufl.i18n
You may contact the author via barry@python.org.
Copyright
=========
Copyright (C) 2009-2014 Barry A. Warsaw
This file is part of flufl.i18n
flufl.i18n is free software: you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
flufl.i18n is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License along
with flufl.i18n. If not, see .
Table of Contents
=================
.. toctree::
:glob:
docs/using
docs/*
NEWS
.. _`simple guide`: docs/using.html
.. _`virtualenv`: http://www.virtualenv.org/en/latest/index.html
flufl.i18n-1.1.3/flufl/i18n/tests/ 0000775 0001750 0001750 00000000000 12326554745 016732 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/tests/test_translator.py 0000664 0001750 0001750 00000010426 12316276127 022531 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Tests for the Translator class.
This cannot be a doctest because of the sys._getframe() manipulations. That
does not play well with the way doctest executes Python code. But see
translator.txt for a description of how this should work in real Python code.
"""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
]
import unittest
from flufl.i18n._translator import Translator
# Some globals for following tests.
purple = 'porpoises'
magenta = 'monkeys'
green = 'gerbil'
class Catalog:
"""Test catalog."""
def __init__(self):
self.translation = None
def ugettext(self, original):
"""Return the translation."""
return self.translation
# For Python 3.
gettext = ugettext
def charset(self):
"""Return the encoding."""
# The default is ascii.
return None
class TranslatorTests(unittest.TestCase):
"""Tests of the Translator class."""
def setUp(self):
self.catalog = Catalog()
# We need depth=1 because we're calling the translation at the same
# level as the locals we care about.
self.translator = Translator(self.catalog, depth=1)
def test_locals(self):
# Test that locals get properly substituted.
aqua = 'aardvarks'
blue = 'badgers'
cyan = 'cats'
self.catalog.translation = '$blue and $cyan and $aqua'
self.assertEqual(self.translator.translate('source string'),
'badgers and cats and aardvarks')
def test_globals(self):
# Test that globals get properly substituted.
self.catalog.translation = '$purple and $magenta and $green'
self.assertEqual(self.translator.translate('source string'),
'porpoises and monkeys and gerbil')
def test_dict_overrides_locals(self):
# Test that explicit mappings override locals.
aqua = 'aardvarks'
blue = 'badgers'
cyan = 'cats'
overrides = dict(blue='bats')
self.catalog.translation = '$blue and $cyan and $aqua'
self.assertEqual(self.translator.translate('source string', overrides),
'bats and cats and aardvarks')
def test_globals_with_overrides(self):
# Test that globals with overrides get properly substituted.
self.catalog.translation = '$purple and $magenta and $green'
overrides = dict(green='giraffe')
self.assertEqual(self.translator.translate('source string', overrides),
'porpoises and monkeys and giraffe')
def test_empty_string(self):
# The empty string is always translated as the empty string.
self.assertEqual(self.translator.translate(''), '')
def test_dedent(self):
# By default, the translated string is always dedented.
aqua = 'aardvarks'
blue = 'badgers'
cyan = 'cats'
self.catalog.translation = """\
These are the $blue
These are the $cyan
These are the $aqua
"""
for line in self.translator.translate('source string').splitlines():
self.assertTrue(line[:5], 'These')
def test_no_dedent(self):
# You can optionally suppress the dedent.
aqua = 'aardvarks'
blue = 'badgers'
cyan = 'cats'
self.catalog.translation = """\
These are the $blue
These are the $cyan
These are the $aqua
"""
translator = Translator(self.catalog, dedent=False)
for line in translator.translate('source string').splitlines():
self.assertTrue(line[:9], ' These')
flufl.i18n-1.1.3/flufl/i18n/tests/__init__.py 0000664 0001750 0001750 00000000000 12316276127 021023 0 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl/i18n/tests/test_documentation.py 0000664 0001750 0001750 00000004715 12316276127 023215 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Test harness for doctests."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'additional_tests',
]
import os
import atexit
import doctest
import unittest
from pkg_resources import (
resource_filename, resource_exists, resource_listdir, cleanup_resources)
DOCTEST_FLAGS = (
doctest.ELLIPSIS |
doctest.NORMALIZE_WHITESPACE |
doctest.REPORT_NDIFF)
def setup(testobj):
"""Test setup."""
# Make sure future statements in our doctests match the Python code. When
# run with 2to3, the future import gets removed and these names are not
# defined.
try:
testobj.globs['absolute_import'] = absolute_import
testobj.globs['print_function'] = print_function
testobj.globs['unicode_literals'] = unicode_literals
except NameError:
pass
# Ensure that environment variables affecting translation are neutralized.
for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'):
if envar in os.environ:
del os.environ[envar]
def additional_tests():
"Run the doc tests (README.txt and docs/*, if any exist)"
doctest_files = [
os.path.abspath(resource_filename('flufl.i18n', 'README.rst'))]
if resource_exists('flufl.i18n', 'docs'):
for name in resource_listdir('flufl.i18n', 'docs'):
if name.endswith('.rst'):
doctest_files.append(
os.path.abspath(
resource_filename('flufl.i18n', 'docs/%s' % name)))
kwargs = dict(module_relative=False,
optionflags=DOCTEST_FLAGS,
setUp=setup,
)
atexit.register(cleanup_resources)
return unittest.TestSuite((
doctest.DocFileSuite(*doctest_files, **kwargs)))
flufl.i18n-1.1.3/flufl/i18n/_translator.py 0000664 0001750 0001750 00000010370 12316276127 020465 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Basic translation context class."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
'Translator',
]
import sys
import textwrap
from flufl.i18n._substitute import attrdict, Template
from flufl.i18n._expand import expand
try:
unicode_type = unicode
except NameError:
# Python 3
unicode_type = str
class Translator:
"""A translation context."""
def __init__(self, catalog, dedent=True, depth=2):
"""Create a translation context.
:param catalog: The translation catalog.
:type catalog: `gettext.NullTranslations` or subclass
:param dedent: Whether the input string should be dedented.
:type dedent: bool
:param depth: Number of stack frames to call sys._getframe() with.
:type depth: int
"""
self._catalog = catalog
self.dedent = dedent
self.depth = depth
# Python 3's .gettext() returns unicodes.
try:
self._gettext = self._catalog.ugettext
except AttributeError:
# Must be Python 3, right?
self._gettext = self._catalog.gettext
def translate(self, original, extras=None):
"""Translate the string.
:param original: The original string to translate.
:type original: string
:param extras: Extra substitution mapping, elements of which override
the locals and globals.
:return: The translated string.
:rtype: string
"""
if original == '':
return ''
assert original, 'Cannot translate: {0}'.format(original)
# Because the original string is what the text extractors put into the
# catalog, we must first look up the original unadulterated string in
# the catalog. Use the global translation context for this.
#
# Translations must be unicode safe internally. The translation
# service is one boundary to the outside world, so to honor this
# constraint, make sure that all strings to come out of this are
# unicodes, even if the translated string or dictionary values are
# 8-bit strings.
tns = self._gettext(original)
charset = self._catalog.charset() or 'us-ascii'
# Do PEP 292 style $-string interpolation into the resulting string.
#
# This lets you write something like:
#
# now = time.ctime(time.time())
# print _('The current time is: $now')
#
# and have it Just Work. Key precedence is:
#
# extras > locals > globals
#
# Get the frame of the caller.
frame = sys._getframe(self.depth)
# Create the raw dictionary of substitutions.
raw_dict = frame.f_globals.copy()
raw_dict.update(frame.f_locals)
if extras is not None:
raw_dict.update(extras)
# Python 2 requires ** dictionaries to have str, not unicode keys.
# For our purposes, keys should always be ascii. Values though should
# be unicode.
translated_string = expand(tns, attrdict(raw_dict), Template)
# Use the bytes type here instead of str for better compatibility with
# 2to3, which transforms this code into trying to decode a unicode to
# a unicode.
if isinstance(translated_string, bytes):
translated_string = unicode_type(translated_string, charset)
# Dedent the string if so desired.
if self.dedent:
translated_string = textwrap.dedent(translated_string)
return translated_string
flufl.i18n-1.1.3/tox.ini 0000664 0001750 0001750 00000000124 12316276657 015213 0 ustar barry barry 0000000 0000000 [tox]
envlist = py26,py27,py32,py33,py34
[testenv]
commands = python setup.py test
flufl.i18n-1.1.3/flufl.i18n.egg-info/ 0000775 0001750 0001750 00000000000 12326554745 017261 5 ustar barry barry 0000000 0000000 flufl.i18n-1.1.3/flufl.i18n.egg-info/SOURCES.txt 0000664 0001750 0001750 00000002037 12326554745 021147 0 ustar barry barry 0000000 0000000 COPYING-LESSER.txt
MANIFEST.in
README.rst
setup.cfg
setup.py
setup_helpers.py
template.py
tox.ini
flufl/__init__.py
flufl.i18n.egg-info/PKG-INFO
flufl.i18n.egg-info/SOURCES.txt
flufl.i18n.egg-info/dependency_links.txt
flufl.i18n.egg-info/namespace_packages.txt
flufl.i18n.egg-info/not-zip-safe
flufl.i18n.egg-info/top_level.txt
flufl/i18n/NEWS.rst
flufl/i18n/README.rst
flufl/i18n/__init__.py
flufl/i18n/_application.py
flufl/i18n/_expand.py
flufl/i18n/_registry.py
flufl/i18n/_strategy.py
flufl/i18n/_substitute.py
flufl/i18n/_translator.py
flufl/i18n/conf.py
flufl/i18n/docs/__init__.py
flufl/i18n/docs/expand.rst
flufl/i18n/docs/strategies.rst
flufl/i18n/docs/using.rst
flufl/i18n/testing/__init__.py
flufl/i18n/testing/messages/__init__.py
flufl/i18n/testing/messages/xx/LC_MESSAGES/flufl.mo
flufl/i18n/testing/messages/xx/LC_MESSAGES/flufl.po
flufl/i18n/testing/messages/yy/LC_MESSAGES/flufl.mo
flufl/i18n/testing/messages/yy/LC_MESSAGES/flufl.po
flufl/i18n/tests/__init__.py
flufl/i18n/tests/test_documentation.py
flufl/i18n/tests/test_translator.py flufl.i18n-1.1.3/flufl.i18n.egg-info/top_level.txt 0000664 0001750 0001750 00000000006 12326554745 022007 0 ustar barry barry 0000000 0000000 flufl
flufl.i18n-1.1.3/flufl.i18n.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 12326554745 023327 0 ustar barry barry 0000000 0000000
flufl.i18n-1.1.3/flufl.i18n.egg-info/namespace_packages.txt 0000664 0001750 0001750 00000000006 12326554745 023610 0 ustar barry barry 0000000 0000000 flufl
flufl.i18n-1.1.3/flufl.i18n.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12326554605 021502 0 ustar barry barry 0000000 0000000
flufl.i18n-1.1.3/flufl.i18n.egg-info/PKG-INFO 0000664 0001750 0001750 00000012425 12326554745 020362 0 ustar barry barry 0000000 0000000 Metadata-Version: 1.1
Name: flufl.i18n
Version: 1.1.3
Summary: A high level API for Python internationalization.
Home-page: https://launchpad.net/flufl.i18n
Author: Barry Warsaw
Author-email: barry@python.org
License: LGPLv3
Download-URL: https://launchpad.net/flufl.i18n/+download
Description: ==========
flufl.i18n
==========
A high level API for Python internationalization.
The ``flufl.i18n`` library provides a convenient API for managing translation
contexts in Python applications. It provides facilities not only for
single-context applications like command line scripts, but also more
sophisticated management of multiple-context applications such as Internet
servers.
License
=======
This file is part of flufl.i18n.
flufl.i18n is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, version 3 of the License.
flufl.i18n is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with flufl.i18n. If not, see .
=====================
NEWS for flufl.i18n
=====================
1.1.3 (2014-04-25)
==================
* Include MANIFEST.in in the sdist tarball, otherwise the Debian package
won't built correctly.
1.1.2 (2014-03-31)
==================
* Fix documentation bug. LP: #1026403
* Use modern setuptools rather than distutils.
* Bump copyright years.
1.1.1 (2012-04-19)
==================
* Add classifiers to setup.py and make the long description more compatible
with the Cheeseshop.
* Other changes to make the Cheeseshop page look nicer. (LP: #680136)
* setup_helper.py version 2.1.
1.1 (2012-01-19)
================
* Support Python 3 without the need for 2to3.
1.0.4 (2010-12-06)
==================
* Restore missing line from MANIFEST.in to fix distribution tarball.
1.0.3 (2010-12-01)
==================
* Fix setup.py to not install myfixers artifact directory on install.
* Remove pylint.rc; we'll use pyflakes instead.
1.0.2 (2010-06-23)
==================
* Small documentation fix.
1.0.1 (2010-06-09)
==================
* Ditch the use of zc.buildout.
* Improved documentation.
1.0 (2010-04-24)
================
* Use Distribute instead of Setuptools.
* Port to Python 3 when used with 2to3.
* More documentation improvements.
0.6 (2010-04-21)
================
* Documentation and lint clean up.
0.5 (2010-04-20)
================
* Added a simplified initialization API for one-language-context
applications. This works much better for non-server applications.
* Added a SimpleStrategy which recognizes the $LOCPATH environment variable.
* Show how PEP 292 strings are supported automatically.
* When strategies are called with zero arguments, they supply the default
translation context, which is usually a NullTranslation. This is better
than hardcoding the NullTranslation in the Application.
0.4 (2010-03-04)
================
* Add the ability to get the current language code, via _.code
0.3 (2009-11-15)
================
* Initial release; refactored from Mailman 3.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Internationalization
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Localization
flufl.i18n-1.1.3/COPYING-LESSER.txt 0000664 0001750 0001750 00000016725 12316276127 016552 0 ustar barry barry 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
flufl.i18n-1.1.3/PKG-INFO 0000664 0001750 0001750 00000012425 12326554745 015002 0 ustar barry barry 0000000 0000000 Metadata-Version: 1.1
Name: flufl.i18n
Version: 1.1.3
Summary: A high level API for Python internationalization.
Home-page: https://launchpad.net/flufl.i18n
Author: Barry Warsaw
Author-email: barry@python.org
License: LGPLv3
Download-URL: https://launchpad.net/flufl.i18n/+download
Description: ==========
flufl.i18n
==========
A high level API for Python internationalization.
The ``flufl.i18n`` library provides a convenient API for managing translation
contexts in Python applications. It provides facilities not only for
single-context applications like command line scripts, but also more
sophisticated management of multiple-context applications such as Internet
servers.
License
=======
This file is part of flufl.i18n.
flufl.i18n is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, version 3 of the License.
flufl.i18n is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with flufl.i18n. If not, see .
=====================
NEWS for flufl.i18n
=====================
1.1.3 (2014-04-25)
==================
* Include MANIFEST.in in the sdist tarball, otherwise the Debian package
won't built correctly.
1.1.2 (2014-03-31)
==================
* Fix documentation bug. LP: #1026403
* Use modern setuptools rather than distutils.
* Bump copyright years.
1.1.1 (2012-04-19)
==================
* Add classifiers to setup.py and make the long description more compatible
with the Cheeseshop.
* Other changes to make the Cheeseshop page look nicer. (LP: #680136)
* setup_helper.py version 2.1.
1.1 (2012-01-19)
================
* Support Python 3 without the need for 2to3.
1.0.4 (2010-12-06)
==================
* Restore missing line from MANIFEST.in to fix distribution tarball.
1.0.3 (2010-12-01)
==================
* Fix setup.py to not install myfixers artifact directory on install.
* Remove pylint.rc; we'll use pyflakes instead.
1.0.2 (2010-06-23)
==================
* Small documentation fix.
1.0.1 (2010-06-09)
==================
* Ditch the use of zc.buildout.
* Improved documentation.
1.0 (2010-04-24)
================
* Use Distribute instead of Setuptools.
* Port to Python 3 when used with 2to3.
* More documentation improvements.
0.6 (2010-04-21)
================
* Documentation and lint clean up.
0.5 (2010-04-20)
================
* Added a simplified initialization API for one-language-context
applications. This works much better for non-server applications.
* Added a SimpleStrategy which recognizes the $LOCPATH environment variable.
* Show how PEP 292 strings are supported automatically.
* When strategies are called with zero arguments, they supply the default
translation context, which is usually a NullTranslation. This is better
than hardcoding the NullTranslation in the Application.
0.4 (2010-03-04)
================
* Add the ability to get the current language code, via _.code
0.3 (2009-11-15)
================
* Initial release; refactored from Mailman 3.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)
Classifier: Operating System :: POSIX
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Internationalization
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Localization
flufl.i18n-1.1.3/template.py 0000664 0001750 0001750 00000001466 12316276127 016067 0 ustar barry barry 0000000 0000000 # Copyright (C) 2009-2014 by Barry A. Warsaw
#
# This file is part of flufl.i18n
#
# flufl.i18n is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# flufl.i18n is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with flufl.i18n. If not, see .
"""Module contents."""
from __future__ import absolute_import, print_function, unicode_literals
__metaclass__ = type
__all__ = [
]
flufl.i18n-1.1.3/README.rst 0000664 0001750 0001750 00000001774 12316276127 015373 0 ustar barry barry 0000000 0000000 ==========
flufl.i18n
==========
A high level API for Python internationalization.
The ``flufl.i18n`` library provides a convenient API for managing translation
contexts in Python applications. It provides facilities not only for
single-context applications like command line scripts, but also more
sophisticated management of multiple-context applications such as Internet
servers.
License
=======
This file is part of flufl.i18n.
flufl.i18n is free software: you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, version 3 of the License.
flufl.i18n is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
License for more details.
You should have received a copy of the GNU Lesser General Public License
along with flufl.i18n. If not, see .