summaryrefslogtreecommitdiff
path: root/src/zope/i18n/translationdomain.py
diff options
context:
space:
mode:
authorMalthe Borch <mborch@gmail.com>2012-10-10 09:25:17 +0000
committerMalthe Borch <mborch@gmail.com>2012-10-10 09:25:17 +0000
commit5a97e5eb26863c0338af9ef0a1646011ff59ba6c (patch)
tree08bb6ac1b2a259148e266dfe3b794986ffb60e45 /src/zope/i18n/translationdomain.py
parent1f8c08bee94884b6cd25465f74ceabc508bc0b21 (diff)
downloadzope-i18n-5a97e5eb26863c0338af9ef0a1646011ff59ba6c.tar.gz
The ZCML directive handler for a translation domain registration now
loads message catalogs lazily. If the `zope_i18n_allowed_languages` environment variable is not provided, the allowed languages are determined at runtime. To participate in this, a translation domain implementation must now expose a set of languages in a ``languages`` attribute. The difficulty in this patch is that the ``INegotiator`` interface relies on an "allowed languages" set, but this set is not readily available. In the current definition of a translation domain, we can't know until we attempt a translation whether a language is supported. The solution in this patch is to require that a translation domain exposes the defined languages and then query all translation domains to determine the allowed languages. It would be nice if we could just provide a value of ``None`` (meaning any language), but there's already existing implementations that expect a set.
Diffstat (limited to 'src/zope/i18n/translationdomain.py')
-rw-r--r--src/zope/i18n/translationdomain.py23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/zope/i18n/translationdomain.py b/src/zope/i18n/translationdomain.py
index dfc7f41..2faa301 100644
--- a/src/zope/i18n/translationdomain.py
+++ b/src/zope/i18n/translationdomain.py
@@ -17,7 +17,9 @@ import zope.component
from zope.i18nmessageid import Message
from zope.i18n import translate, interpolate
from zope.i18n.simpletranslationdomain import SimpleTranslationDomain
-from zope.i18n.interfaces import ITranslationDomain, INegotiator
+from zope.i18n.interfaces import INegotiator
+from zope.i18n.compile import compile_mo_file
+from zope.i18n.gettextmessagecatalog import GettextMessageCatalog
# The configuration should specify a list of fallback languages for the
# site. If a particular catalog for a negotiated language is not available,
@@ -31,6 +33,7 @@ LANGUAGE_FALLBACKS = ['en']
class TranslationDomain(SimpleTranslationDomain):
+ languages = ()
def __init__(self, domain, fallbacks=None):
self.domain = domain
@@ -43,22 +46,34 @@ class TranslationDomain(SimpleTranslationDomain):
if fallbacks is None:
fallbacks = LANGUAGE_FALLBACKS
self._fallbacks = fallbacks
+ self._pending = {}
+ self.languages = set()
def _registerMessageCatalog(self, language, catalog_name):
key = language
mc = self._catalogs.setdefault(key, [])
mc.append(catalog_name)
+ self.languages.add(language)
def addCatalog(self, catalog):
self._data[catalog.getIdentifier()] = catalog
self._registerMessageCatalog(catalog.language,
catalog.getIdentifier())
+ def addLanguage(self, lang, path):
+ self._pending.setdefault(lang, []).append(path)
+ self.languages.add(lang)
+
def setLanguageFallbacks(self, fallbacks=None):
if fallbacks is None:
fallbacks = LANGUAGE_FALLBACKS
self._fallbacks = fallbacks
+ def importCatalog(self, lang, lc_messages_path):
+ path = compile_mo_file(self.domain, lc_messages_path)
+ catalog = GettextMessageCatalog(lang, self.domain, path)
+ self.addCatalog(catalog)
+
def translate(self, msgid, mapping=None, context=None,
target_language=None, default=None):
"""See zope.i18n.interfaces.ITranslationDomain"""
@@ -74,6 +89,10 @@ class TranslationDomain(SimpleTranslationDomain):
# try to determine target language from negotiator utility
target_language = negotiator.getLanguage(langs, context)
+ paths = self._pending.pop(target_language, ())
+ for path in paths:
+ self.importCatalog(target_language, path)
+
return self._recursive_translate(
msgid, mapping, target_language, default, context)
@@ -124,7 +143,7 @@ class TranslationDomain(SimpleTranslationDomain):
# this is a slight optimization for the case when there is a
# single catalog. More importantly, it is extremely helpful
# when testing and the test language is used, because it
- # allows the test language to get the default.
+ # allows the test language to get the default.
text = self._data[catalog_names[0]].queryMessage(
msgid, default)
else: