From 06a56614cbaf4ca97557bf174eb6573ca78288c1 Mon Sep 17 00:00:00 2001 From: cmlenz Date: Mon, 20 Aug 2007 10:06:57 +0000 Subject: [PATCH] Add Django integration code contributed by Ramiro Morales and Massimo Scamarcia. git-svn-id: http://svn.edgewall.org/repos/babel/contrib/django@292 59ecc08e-a131-0410-9ea7-d4c0f28ac310 --- COPYING | 28 ++++++++++ README.txt | 12 +++++ babeldjango/__init__.py | 12 +++++ babeldjango/extract.py | 108 ++++++++++++++++++++++++++++++++++++++ babeldjango/middleware.py | 44 ++++++++++++++++ setup.cfg | 3 ++ setup.py | 36 +++++++++++++ 7 files changed, 243 insertions(+) create mode 100644 COPYING create mode 100644 README.txt create mode 100644 babeldjango/__init__.py create mode 100644 babeldjango/extract.py create mode 100644 babeldjango/middleware.py create mode 100644 setup.cfg create mode 100755 setup.py diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..74202d4 --- /dev/null +++ b/COPYING @@ -0,0 +1,28 @@ +Copyright (C) 2007 Edgewall Software +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..d3b3047 --- /dev/null +++ b/README.txt @@ -0,0 +1,12 @@ +Tools for using Babel with Django +================================= + +This package contains various utilities for integration of Babel into the +Django web framework: + + * A message extraction plugin for Django templates. + * A middleware class that adds the Babel `Locale` object to requests. + +For more information please visit the wiki page for this package: + + diff --git a/babeldjango/__init__.py b/babeldjango/__init__.py new file mode 100644 index 0000000..0d752c6 --- /dev/null +++ b/babeldjango/__init__.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://babel.edgewall.org/wiki/License. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://babel.edgewall.org/log/. diff --git a/babeldjango/extract.py b/babeldjango/extract.py new file mode 100644 index 0000000..8801d3d --- /dev/null +++ b/babeldjango/extract.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://babel.edgewall.org/wiki/License. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://babel.edgewall.org/log/. + +from babel.core import * + +from django.conf import settings +settings.configure(USE_I18N=True) +from django.template import Lexer, TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK +from django.utils.translation.trans_real import inline_re, block_re, \ + endblock_re, plural_re, \ + constant_re + +def extract_django(fileobj, keywords, comment_tags, options): + """Extract messages from Django template files. + + :param fileobj: the file-like object the messages should be extracted from + :param keywords: a list of keywords (i.e. function names) that should + be recognized as translation functions + :param comment_tags: a list of translator tags to search for and + include in the results + :param options: a dictionary of additional options (optional) + :return: an iterator over ``(lineno, funcname, message, comments)`` + tuples + :rtype: ``iterator`` + """ + intrans = False + inplural = False + singular = [] + plural = [] + lineno = 1 + for t in Lexer(fileobj.read(), None).tokenize(): + lineno += t.contents.count('\n') + if intrans: + if t.token_type == TOKEN_BLOCK: + endbmatch = endblock_re.match(t.contents) + pluralmatch = plural_re.match(t.contents) + if endbmatch: + if inplural: + yield lineno, 'ngettext', (unicode(''.join(singular)), + unicode(''.join(plural))), [] + else: + yield lineno, None, unicode(''.join(singular)), [] + intrans = False + inplural = False + singular = [] + plural = [] + elif pluralmatch: + inplural = True + else: + raise SyntaxError('Translation blocks must not include ' + 'other block tags: %s' % t.contents) + elif t.token_type == TOKEN_VAR: + if inplural: + plural.append('%%(%s)s' % t.contents) + else: + singular.append('%%(%s)s' % t.contents) + elif t.token_type == TOKEN_TEXT: + if inplural: + plural.append(t.contents) + else: + singular.append(t.contents) + else: + if t.token_type == TOKEN_BLOCK: + imatch = inline_re.match(t.contents) + bmatch = block_re.match(t.contents) + cmatches = constant_re.findall(t.contents) + if imatch: + g = imatch.group(1) + if g[0] == '"': + g = g.strip('"') + elif g[0] == "'": + g = g.strip("'") + yield lineno, None, unicode(g), [] + elif bmatch: + intrans = True + inplural = False + singular = [] + plural = [] + elif cmatches: + for cmatch in cmatches: + yield lineno, None, unicode(cmatch), [] + elif t.token_type == TOKEN_VAR: + parts = t.contents.split('|') + cmatch = constant_re.match(parts[0]) + if cmatch: + yield lineno, None, unicode(cmatch.group(1)), [] + for p in parts[1:]: + if p.find(':_(') >= 0: + p1 = p.split(':',1)[1] + if p1[0] == '_': + p1 = p1[1:] + if p1[0] == '(': + p1 = p1.strip('()') + if p1[0] == "'": + p1 = p1.strip("'") + elif p1[0] == '"': + p1 = p1.strip('"') + yield lineno, None, unicode(p1), [] diff --git a/babeldjango/middleware.py b/babeldjango/middleware.py new file mode 100644 index 0000000..a697afe --- /dev/null +++ b/babeldjango/middleware.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://babel.edgewall.org/wiki/License. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://babel.edgewall.org/log/. + +from babel import Locale, UnknownLocaleError +try: + from threading import local +except ImportError: + from django.utils._threading_local import local + +__all__ = ['get_current_locale', 'LocaleMiddleware'] + +_thread_locals = local() + +def get_current_locale(): + """Get current locale data outside views. + + See http://babel.edgewall.org/wiki/ApiDocs/babel.core for Locale + objects documentation + """ + return getattr(_thread_locals, 'locale', None) + + +class LocaleMiddleware(object): + """Simple Django middleware that makes available a Babel `Locale` object + via the `request.locale` attribute. + """ + + def process_request(self, request): + try: + locale = Locale.parse(request.LANGUAGE_CODE, sep='-') + except (ValueError, UnknownLocaleError): + pass + else: + _thread_locals.locale = request.locale = locale diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..01bb954 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[egg_info] +tag_build = dev +tag_svn_revision = true diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..826386e --- /dev/null +++ b/setup.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright (C) 2007 Edgewall Software +# All rights reserved. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at http://babel.edgewall.org/wiki/License. +# +# This software consists of voluntary contributions made by many +# individuals. For the exact contribution history, see the revision +# history and logs, available at http://babel.edgewall.org/log/. + +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + +setup( + name = 'BabelDjango', + description = 'Utilities for using Babel in Django', + version = '0.1', + license = 'BSD', + author = 'Edgewall Software', + author_email = 'python-babel@googlegroups.com', + url = 'http://babel.edgewall.org/wiki/BabelDjango', + + packages = ['babeldjango'], + install_requires = ['Babel'], + + entry_points = """ + [babel.extractors] + django = babeldjango.extract:extract_django + """, +)