summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorGeorg Bauer <gb@hugo.westfalen.de>2005-10-19 23:55:37 +0000
committerGeorg Bauer <gb@hugo.westfalen.de>2005-10-19 23:55:37 +0000
commit72dcdd4de14b3516bf082bebe5e6f36fd1a36b7c (patch)
treef51a1658711f25b32f9ae3ac6cb71cae815a8a9d /django
parent6ec8d14619ef9c523dec0d21b6eb8fd10a5f60a2 (diff)
i18n: reworked part of the translation loader to be cleaner, simpler and faster
git-svn-id: http://code.djangoproject.com/svn/django/branches/i18n@964 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
-rwxr-xr-xdjango/bin/django-admin.py2
-rw-r--r--django/middleware/locale.py28
-rw-r--r--django/utils/translation.py143
3 files changed, 87 insertions, 86 deletions
diff --git a/django/bin/django-admin.py b/django/bin/django-admin.py
index e9e72a9b73..6af3552a35 100755
--- a/django/bin/django-admin.py
+++ b/django/bin/django-admin.py
@@ -6,7 +6,7 @@ import os, sys
# switch to english, because django-admin creates database content
# like permissions, and those shouldn't contain any translations
-translation.activate('*', 'en-us')
+translation.activate('en-us')
ACTION_MAPPING = {
'adminindex': management.get_admin_index,
diff --git a/django/middleware/locale.py b/django/middleware/locale.py
index a198aeecb8..83ecbdcc67 100644
--- a/django/middleware/locale.py
+++ b/django/middleware/locale.py
@@ -3,9 +3,6 @@
from django.utils.cache import patch_vary_headers
from django.utils import translation
-# this is a cache that will build a map from modules to applications
-_module_to_app = {}
-
class LocaleMiddleware:
"""
This is a very simple middleware that parses a request
@@ -15,30 +12,13 @@ class LocaleMiddleware:
is available, of course).
"""
- def process_view(self, request, view_func, param_dict):
- global _module_to_app
-
- def findapp(module):
- app = _module_to_app.get(view_func.__module__, None)
- if app is not None:
- return app
-
- from django.conf import settings
- for app in settings.INSTALLED_APPS:
- if module.startswith(app):
- _module_to_app[module] = app
- return app
- return '*'
-
- app = findapp(view_func.__module__)
-
- lang = translation.get_language_from_request(request)
-
- translation.activate(app, lang)
-
+ def process_request(self, request):
+ language = translation.get_language_from_request(request)
+ translation.activate(language)
request.LANGUAGE_CODE = translation.get_language()
def process_response(self, request, response):
patch_vary_headers(response, ('Accept-Language',))
+ translation.deactivate()
return response
diff --git a/django/utils/translation.py b/django/utils/translation.py
index 4f06053942..0737d9a0cd 100644
--- a/django/utils/translation.py
+++ b/django/utils/translation.py
@@ -36,7 +36,7 @@ def to_locale(language):
"turn a language name (en-us) into a locale name (en_US)"
p = language.find('-')
if p >= 0:
- return language[:p].lower()+'_'+language[p:].upper()
+ return language[:p].lower()+'_'+language[p+1:].upper()
else:
return language.lower()
@@ -44,7 +44,7 @@ def to_language(locale):
"turns a locale name (en_US) into a language name (en-us)"
p = locale.find('_')
if p >= 0:
- return locale[:p].lower()+'-'+locale[p:].lower()
+ return locale[:p].lower()+'-'+locale[p+1:].lower()
else:
return locale.lower()
@@ -67,18 +67,19 @@ class DjangoTranslation(gettext_module.GNUTranslations):
except AttributeError:
pass
self.django_output_charset = settings.DEFAULT_CHARSET
- self.__app = '?.?.?'
self.__language = '??'
+
+ def merge(self, other):
+ self._catalog.update(other._catalog)
- def set_app_and_language(self, app, language):
- self.__app = app
+ def set_language(self, language):
self.__language = language
def language(self):
return self.__language
def __repr__(self):
- return "<DjangoTranslation app:%s lang:%s>" % (self.__app, self.__language)
+ return "<DjangoTranslation lang:%s>" % self.__language
class DjangoTranslation23(DjangoTranslation):
@@ -101,28 +102,27 @@ class DjangoTranslation23(DjangoTranslation):
res = self.ungettext(msgid1, msgid2, n)
return res.encode(self.django_output_charset)
-def translation(appname, language):
+def translation(language):
"""
- This function returns a translation object.
- app must be the fully qualified name of the
- application.
+ This function returns a translation object. app must be the fully
+ qualified name of the application.
- This function will first look into the app
- messages directory for the django message file,
- then in the project messages directory for the
- django message file and last in the global
- messages directory for the django message file.
+ This translation object will be constructed out of multiple GNUTranslations
+ objects by merging their catalogs. It will construct a object for the requested
+ language and add a fallback to the default language, if that is different
+ from the requested language.
"""
+ global _translations
+
+ if language == 'en' or language.startswith('en-'):
+ return gettext_module.NullTranslations()
- t = _translations.get((appname, language), None)
+ t = _translations.get(language, None)
if t is not None:
return t
from django.conf import settings
- default_locale = to_locale(settings.LANGUAGE_CODE)
- locale = to_locale(language)
-
# set up the right translation class
klass = DjangoTranslation
if sys.version_info < (2, 4):
@@ -130,61 +130,79 @@ def translation(appname, language):
globalpath = os.path.join(os.path.dirname(settings.__file__), 'locale')
- try:
- t = gettext_module.translation('django', globalpath, [locale, default_locale], klass)
- t.set_app_and_language(appname, language)
- except IOError: t = gettext_module.NullTranslations()
- _translations[(appname, language)] = t
+ parts = os.environ['DJANGO_SETTINGS_MODULE'].split('.')
+ project = __import__(parts[0], {}, {}, [])
+ projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
+
+ def _fetch(lang, fallback=None):
+
+ global _translations
+
+ loc = to_locale(lang)
+
+ res = _translations.get(lang, None)
+ if res is not None:
+ return res
- if hasattr(settings, 'LOCALE_PATHS'):
- for localepath in settings.LOCALE_PATHS:
+ def _translation(path):
try:
- t = gettext_module.translation('django', localepath, [locale, default_locale], klass)
- t.set_app_and_language(appname, language)
- except IOError: t = None
+ t = gettext_module.translation('django', path, [loc], klass)
+ t.set_language(lang)
+ return t
+ except IOError, e:
+ return None
+
+ res = _translation(globalpath)
+
+ def _merge(path):
+ t = _translation(path)
if t is not None:
- t.add_fallback(_translations[(appname, language)])
- _translations[(appname, language)] = t
+ if res is None:
+ return t
+ else:
+ res.merge(t)
+ return res
- parts = os.environ['DJANGO_SETTINGS_MODULE'].split('.')
- project = __import__(parts[0], {}, {}, [])
+ if hasattr(settings, 'LOCALE_PATHS'):
+ for localepath in settings.LOCALE_PATHS:
+ if os.path.isdir(localepath):
+ res = _merge(localepath)
- projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
+ if os.path.isdir(projectpath):
+ res = _merge(projectpath)
- try:
- t = gettext_module.translation('django', projectpath, [locale, default_locale], klass)
- t.set_app_and_language(appname, language)
- except IOError: t = None
- if t is not None:
- t.add_fallback(_translations[(appname, language)])
- _translations[(appname, language)] = t
+ for appname in settings.INSTALLED_APPS:
+ p = appname.rfind('.')
+ if p >= 0:
+ app = getattr(__import__(appname[:p], {}, {}, [appname[p+1:]]), appname[p+1:])
+ else:
+ app = __import__(appname, {}, {}, [])
- if appname != '*':
- app = __import__(appname, {}, {}, ['views'])
+ apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
- apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
+ if os.path.isdir(apppath):
+ res = _merge(apppath)
+
+ if res is None:
+ if fallback is not None:
+ res = fallback
+ else:
+ return gettext_module.NullTranslations()
+ _translations[lang] = res
+ return res
- try:
- t = gettext_module.translation('django', apppath, [locale, default_locale], klass)
- t.set_app_and_language(appname, language)
- except IOError: t = None
- if t is not None:
- t.add_fallback(_translations[(appname, language)])
- _translations[(appname, language)] = t
+ default_translation = _fetch(settings.LANGUAGE_CODE)
+ current_translation = _fetch(language, fallback=default_translation)
- return _translations[(appname, language)]
+ return current_translation
-def activate(appname, language):
+def activate(language):
"""
This function fetches the translation object for a given
tuple of application name and language and installs it as
the current translation object for the current thread.
"""
- if language == 'en' or language.startswith('en-'):
- t = gettext_module.NullTranslations()
- else:
- t = translation(appname, language)
- _active[currentThread()] = t
+ _active[currentThread()] = translation(language)
def deactivate():
"""
@@ -192,7 +210,10 @@ def deactivate():
object so that further _ calls will resolve against the
default translation object, again.
"""
- del _active[currentThread()]
+ global _active
+
+ if _active.has_key(currentThread()):
+ del _active[currentThread()]
def get_language():
"""
@@ -225,7 +246,7 @@ def gettext(message):
return t.gettext(message)
if _default is None:
from django.conf import settings
- _default = translation('*', settings.LANGUAGE_CODE)
+ _default = translation(settings.LANGUAGE_CODE)
return _default.gettext(message)
def gettext_noop(message):
@@ -335,7 +356,7 @@ def get_language_from_request(request):
# report de_DE if we only have de available, but
# did find de_DE because of language normalization
lang = langfile[len(globalpath):].split('/')[1]
- _accepted[accept] = to_language(lang)
+ _accepted[accept] = lang
return lang
return settings.LANGUAGE_CODE