[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[OpenTAL-checkins] CVSROOT: /cvsroot/opental
From: |
Sidnei da Silva |
Subject: |
[OpenTAL-checkins] CVSROOT: /cvsroot/opental |
Date: |
Sun, 14 Sep 2003 20:07:42 -0400 |
Module name: opental
Branch: no_more_readconflict
Changes by: Sidnei da Silva <address@hidden> 03/09/14 20:07:41
Reply-to: address@hidden
CVSROOT: /cvsroot/opental
Module name: opental
Branch: no_more_readconflict
Changes by: Sidnei da Silva <address@hidden> 03/09/14 20:07:41
Modified files:
PlacelessTranslationService: GettextMessageCatalog.py
PlacelessTranslationService.py
__init__.py
Log message:
A try at getting rid of ReadConflictErrors and other __setstate__
oddities
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/GettextMessageCatalog.py.diff?only_with_tag=no_more_readconflict&tr1=1.14&tr2=1.14.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/PlacelessTranslationService.py.diff?only_with_tag=no_more_readconflict&tr1=1.26&tr2=1.26.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/__init__.py.diff?only_with_tag=no_more_readconflict&tr1=1.14&tr2=1.14.2.1&r1=text&r2=text
Patches:
Index: opental/PlacelessTranslationService/GettextMessageCatalog.py
diff -u /dev/null
opental/PlacelessTranslationService/GettextMessageCatalog.py:1.14.2.1
--- /dev/null Sun Sep 14 20:07:41 2003
+++ opental/PlacelessTranslationService/GettextMessageCatalog.py Sun Sep
14 20:07:41 2003
@@ -0,0 +1,235 @@
+##############################################################################
+# Copyright (C) 2001, 2002, 2003 Lalo Martins <address@hidden>,
+# Zope Corporation and Contributors
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+"""A simple implementation of a Message Catalog.
+
+$Id: GettextMessageCatalog.py,v 1.14.2.1 2003/09/15 00:07:41 dreamcatcher Exp $
+"""
+
+from gettext import GNUTranslations
+import os, types, codecs
+from types import DictType, StringType, UnicodeType
+from OFS.Traversable import Traversable
+from Persistence import Persistent
+from Acquisition import Implicit
+from App.Management import Tabs
+from PlacelessTranslationService import log, Registry
+try:
+ True
+except NameError:
+ True=1
+ False=0
+
+try:
+ from Products.OpenPT.OpenPTFile import OpenPTFile as ptFile
+except ImportError:
+ from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+ from Globals import package_home
+ def ptFile(id, *filename):
+ if type(filename[0]) is types.DictType:
+ filename = list(filename)
+ filename[0] = package_home(filename[0])
+ filename = os.path.join(*filename)
+ if not os.path.splitext(filename)[1]:
+ filename = filename + '.pt'
+ return PageTemplateFile(filename, '', __name__=id)
+
+# template to use to write missing entries to .missing
+missing_template = u"""msgid "%(id)s"
+msgstr ""
+"""
+
+orig_text_template = u"""
+#. %(text)s
+"""
+
+orig_text_line_joiner = u"\n#. "
+
+permission = 'View management screens'
+
+translationRegistry = Registry()
+registerTranslation = translationRegistry.register
+
+class GettextMessageCatalog(Persistent, Implicit, Traversable, Tabs):
+ """
+ Message catalog that wraps a .mo file in the filesystem
+ """
+ meta_type = title = 'Gettext Message Catalog'
+ icon = 'misc_/PlacelessTranslationService/GettextMessageCatalog.png'
+ __roles__=('Manager',)
+ title__roles__=__roles__
+
+ def __init__(self, path_to_file):
+ """Initialize the message catalog"""
+ self._path_to_file = path_to_file
+ self.id = os.path.split(self._path_to_file)[-1]
+ #self.id = self._path_to_file.replace('/', '::')
+ self._prepareTranslations()
+
+ def _prepareTranslations(self):
+ """ """
+ tro = None
+ if getattr(self, '_v_tro', None) is None:
+ self._v_tro = tro = translationRegistry.get(self.id, None)
+ if tro is None:
+ file = open(self._path_to_file, 'rb')
+ tro = GNUTranslations(file)
+ file.close()
+ self._language = (tro._info.get('language-code', None) # new way
+ or tro._info.get('language', None)) # old way
+ self._domain = tro._info.get('domain', None)
+ if self._language is None or self._domain is None:
+ raise ValueError, 'potfile has no metadata'
+ self._language = self._language.lower().replace('_', '-')
+ self._other_languages = tro._info.get('x-is-fallback-for',
'').split()
+ self.preferred_encodings = tro._info.get('preferred-encodings',
'').split()
+ self.name = unicode(tro._info.get('language-name', ''),
tro._charset)
+ self.default_zope_data_encoding = tro._charset
+ translationRegistry[self.id] = self._v_tro = tro
+ self._missing = self._path_to_file[:-1] + 'issing'
+ if not os.access(self._missing, os.W_OK):
+ self._missing = None
+ if self.name:
+ self.title = '%s language (%s) for %s' % (self._language,
self.name, self._domain)
+ else:
+ self.title = '%s language for %s' % (self._language,
self._domain)
+
+ def filtered_manage_options(self, REQUEST=None):
+ return self.manage_options
+
+ def reload(self, REQUEST=None):
+ "Forcibly re-read the file"
+ if self.id in translationRegistry.keys():
+ del translationRegistry[self.id]
+ if hasattr(self, '_v_tro'):
+ del self._v_tro
+ self._prepareTranslations()
+ log('reloading %s: %s' % (self.id, self.title))
+ if hasattr(REQUEST, 'RESPONSE'):
+ REQUEST.RESPONSE.redirect(self.absolute_url())
+
+ def _log_missing(self, id, orig_text):
+ if self._missing is None:
+ return
+ if getattr(self, '_v_missing', None) is None:
+ self._v_missing = codecs.open(self._missing, 'a',
+ self._v_tro._charset)
+ if orig_text:
+ orig_text = orig_text_line_joiner.join(orig_text.split('\n'))
+ self._v_missing.write(orig_text_template % {'text': orig_text})
+ self._v_missing.write(missing_template % {'id':id.replace('"', r'\"')})
+ self._v_missing.flush()
+
+ def getMessage(self, id, orig_text=None, testing=False):
+ """
+ """
+ self._prepareTranslations()
+ msg = self._v_tro.gettext(id)
+ if msg is id:
+ if not testing:
+ self._log_missing(id, orig_text)
+ raise KeyError
+ if type(msg) is StringType:
+ msg = unicode(msg, self._v_tro._charset)
+ return msg
+
+ queryMessage__roles__=None # Public
+ def queryMessage(self, id, default=None):
+ """
+ """
+ try:
+ return self.getMessage(id, default, testing=True)
+ except KeyError:
+ if default is None:
+ default = id
+ return default
+
+ def getLanguage(self):
+ """
+ """
+ return self._language
+
+ def getLanguageName(self):
+ """
+ """
+ return self.name or self._language
+
+ def getOtherLanguages(self):
+ """
+ """
+ return self._other_languages
+
+ def getDomain(self):
+ """
+ """
+ return self._domain
+
+ def getIdentifier(self):
+ """
+ """
+ return self.id
+
+ def getId(self):
+ """
+ """
+ return self.id
+
+ def getInfo(self, name):
+ """
+ """
+ self._prepareTranslations()
+ return self._v_tro._info.get(name, None)
+
+ Title__roles__ = __roles__
+ def Title(self):
+ return self.title
+
+ ############################################################
+ # Zope/OFS integration
+
+ def manage_afterAdd(self, item, container): pass
+ def manage_beforeDelete(self, item, container): pass
+ def manage_afterClone(self, item): pass
+
+ manage_options = (
+ {'label':'Info', 'action':''},
+ {'label':'Test', 'action':'zmi_test'},
+ )
+
+ index_html = ptFile('index_html', globals(), 'www', 'catalog_info')
+
+ zmi_test = ptFile('zmi_test', globals(), 'www', 'catalog_test')
+
+ file_exists__roles__ = __roles__
+ def file_exists(self):
+ try:
+ file = open(self._path_to_file, 'rb')
+ except:
+ return False
+ return True
+
+ displayInfo__roles__ = __roles__
+ def displayInfo(self):
+ self._prepareTranslations()
+ info = self._v_tro._info
+ keys = info.keys()
+ keys.sort()
+ return [{'name': k, 'value': info[k]} for k in keys] + [
+ {'name': 'full path', 'value': self._path_to_file},
+ ]
+ #
+ ############################################################
Index: opental/PlacelessTranslationService/PlacelessTranslationService.py
diff -u /dev/null
opental/PlacelessTranslationService/PlacelessTranslationService.py:1.26.2.1
--- /dev/null Sun Sep 14 20:07:41 2003
+++ opental/PlacelessTranslationService/PlacelessTranslationService.py Sun Sep
14 20:07:41 2003
@@ -0,0 +1,347 @@
+##############################################################################
+# Copyright (C) 2001, 2002, 2003 Lalo Martins <address@hidden>,
+# Zope Corporation and Contributors
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+"""Placeless Translation Service for providing I18n to file-based code.
+
+$Id: PlacelessTranslationService.py,v 1.26.2.1 2003/09/15 00:07:41
dreamcatcher Exp $
+"""
+
+import sys, re, zLOG, Globals, fnmatch
+from AccessControl import ClassSecurityInfo
+from OFS.Folder import Folder
+from types import DictType, StringType, UnicodeType
+from Negotiator import negotiator
+from Domain import Domain
+import os
+try:
+ from pax import XML
+except:
+ def XML(v):
+ return str(v)
+try:
+ True
+except NameError:
+ True=1
+ False=0
+_marker = []
+
+
+def log(msg, severity=zLOG.INFO, detail='', error=None):
+ if type(msg) is UnicodeType:
+ msg = msg.encode(sys.getdefaultencoding(), 'replace')
+ if type(detail) is UnicodeType:
+ detail = detail.encode(sys.getdefaultencoding(), 'replace')
+ zLOG.LOG('PlacelessTranslationService', severity, msg, detail, error)
+
+def map_get(map, name):
+ return map.get(name)
+
+# Setting up some regular expressions for finding interpolation variables in
+# the text.
+NAME_RE = r"[a-zA-Z][a-zA-Z0-9_]*"
+_interp_regex = re.compile(r'(?<!\$)(\$(?:%(n)s|{%(n)s}))' %({'n': NAME_RE}))
+_get_var_regex = re.compile(r'%(n)s' %({'n': NAME_RE}))
+
+
+# The configure.zcml file should specify a list of fallback languages for the
+# site. If a particular catalog for a negotiated language is not available,
+# then the zcml specified order should be tried. If that fails, then as a
+# last resort the languages in the following list are tried. If these fail
+# too, then the msgid is returned.
+#
+# Note that these fallbacks are used only to find a catalog. If a particular
+# message in a catalog is not translated, tough luck, you get the msgid.
+LANGUAGE_FALLBACKS = list(os.environ.get('LANGUAGE_FALLBACKS', 'en').split('
'))
+
+from UserDict import UserDict
+
+class Registry(UserDict):
+
+ def register(self, name, value):
+ self[name] = value
+
+catalogRegistry = Registry()
+registerCatalog = catalogRegistry.register
+fbcatalogRegistry = Registry()
+registerFBCatalog = fbcatalogRegistry.register
+
+class PlacelessTranslationService(Folder):
+ meta_type = title = 'Placeless Translation Service'
+ icon = 'misc_/PlacelessTranslationService/PlacelessTranslationService.png'
+ # major, minor, patchlevel, internal
+ # internal is always 0 on releases; if you hack this internally, increment
it
+ _class_version = (0, 5, 0, 1)
+ all_meta_types = ()
+
+ security = ClassSecurityInfo()
+ security.declarePublic('negotiate')
+ security.declarePublic('translate')
+ security.declarePublic('getLanguages')
+ security.declarePublic('getLanguageName')
+
+ def __init__(self, default_domain='global', fallbacks=None):
+ self._instance_version = self._class_version
+ # XXX We haven't specified that ITranslationServices have a default
+ # domain. So far, we've required the domain argument to .translate()
+ self._domain = default_domain
+ # _catalogs maps (language, domain) to identifiers
+ catalogRegistry = {}
+ fbcatalogRegistry = {}
+ # What languages to fallback to, if there is no catalog for the
+ # requested language (no fallback on individual messages)
+ if fallbacks is None:
+ fallbacks = LANGUAGE_FALLBACKS
+ self._fallbacks = fallbacks
+
+ def _registerMessageCatalog(self, catalog):
+ domain = catalog.getDomain()
+ catalogRegistry.setdefault((catalog.getLanguage(), domain),
[]).append(catalog.getIdentifier())
+ for lang in catalog.getOtherLanguages():
+ fbcatalogRegistry.setdefault((lang, domain),
[]).append(catalog.getIdentifier())
+ self._p_changed = 1
+
+ def _unregister_inner(self, catalog, clist):
+ for key, combo in clist.items():
+ try:
+ combo.remove(catalog.getIdentifier())
+ except ValueError:
+ continue
+ if not combo: # removed the last catalog for a language/domain
combination
+ del clist[key]
+
+ def _unregisterMessageCatalog(self, catalog):
+ self._unregister_inner(catalog, catalogRegistry)
+ self._unregister_inner(catalog, fbcatalogRegistry)
+ self._p_changed = 1
+
+ def _load_dir(self, basepath):
+ from GettextMessageCatalog import GettextMessageCatalog
+ log('looking into ' + basepath, zLOG.BLATHER)
+ if not os.path.isdir(basepath):
+ log('it does not exist', zLOG.BLATHER)
+ return
+ names = fnmatch.filter(os.listdir(basepath), '*.mo')
+ if not names:
+ log('nothing found', zLOG.BLATHER)
+ return
+ for name in names:
+ ob = self._getOb(name, _marker)
+ try:
+ if ob is _marker:
+
self.addCatalog(GettextMessageCatalog(os.path.join(basepath, name)))
+ else:
+ self.reloadCatalog(ob)
+ except ValueError:
+ log('Message Catalog has no metadata', zLOG.PROBLEM, name,
sys.exc_info())
+ except:
+ log('Message Catalog has errors', zLOG.PROBLEM, name,
sys.exc_info())
+ log('Initialized:', detail = repr(names) + (' from %s\n' % basepath))
+
+ def manage_renameObject(self, id, new_id, REQUEST=None):
+ "wrap manage_renameObject to deal with registration"
+ catalog = self._getOb(id)
+ self._unregisterMessageCatalog(catalog)
+ Folder.manage_renameObject(self, id, new_id, REQUEST=None)
+ self._registerMessageCatalog(catalog)
+
+ def _delObject(self, id, dp=1):
+ catalog = self._getOb(id)
+ Folder._delObject(self, id, dp)
+ self._unregisterMessageCatalog(catalog)
+
+ def reloadCatalog(self, catalog):
+ # trigger an exception if we don't know anything about it
+ self._getOb(catalog.id)
+ self._unregisterMessageCatalog(catalog)
+ catalog.reload()
+ self._registerMessageCatalog(catalog)
+
+ def addCatalog(self, catalog):
+ try:
+ self._delObject(catalog.id)
+ except:
+ pass
+ self._setObject(catalog.id, catalog, set_owner=False)
+ log('adding %s: %s' % (catalog.id, catalog.title))
+ self._registerMessageCatalog(catalog)
+
+ def setLanguageFallbacks(self, fallbacks=None):
+ if fallbacks is None:
+ fallbacks = LANGUAGE_FALLBACKS
+ self._fallbacks = fallbacks
+
+
+ def getLanguageName(self, code):
+ for (ccode, cdomain), cnames in catalogRegistry.items():
+ if ccode == code:
+ for cname in cnames:
+ cat = self._getOb(cname)
+ if cat.name:
+ return cat.name
+
+
+ def getLanguages(self, domain=None):
+ """Get available languages"""
+ if domain is None:
+ # no domain, so user wants 'em all
+ langs = catalogRegistry.keys()
+ # uniquify
+ d = {}
+ for l in langs:
+ d[l[0]] = 1
+ l = d.keys()
+ else:
+ l = [k[0] for k in catalogRegistry.keys() if k[1] == domain]
+ l.sort()
+ return l
+
+ def negotiate(self, langs, context):
+ return negotiator.getLanguage(langs, context)
+
+ def translate(self, domain, msgid, mapping=None, context=None,
+ target_language=None, default=None):
+ """
+ """
+
+ if not msgid:
+ # refuse to translate an empty msgid
+ return default
+
+ # ZPT passes the object as context. That's wrong according to spec.
+ try:
+ context = context.REQUEST
+ except AttributeError:
+ pass
+
+ if target_language is None:
+ target_language = self.negotiate_language(context, domain)
+
+ # Get the translation. Use the specified fallbacks if this fails
+ catalog_names = catalogRegistry.get((target_language, domain), ()) or \
+ fbcatalogRegistry.get((target_language, domain), ())
+ if not catalog_names:
+ for language in self._fallbacks:
+ catalog_names = catalogRegistry.get((language, domain), ())
+ if catalog_names:
+ break
+
+ for name in catalog_names:
+ catalog = self._getOb(name)
+ try:
+ text = catalog.getMessage(msgid, default)
+ except KeyError:
+ # it's not in this catalog, try the next one
+ continue
+ # found! negotiate output encodings now
+ if hasattr(context, 'pt_output_encoding'):
+ # OpenPT
+ if catalog.preferred_encodings:
+ context.pt_output_encoding.restrict(catalog,
catalog.preferred_encodings)
+ else:
+ # ZPT probably
+ # ask HTTPResponse to encode it for us
+ text = context.RESPONSE._encode_unicode(text)
+ break
+ else:
+ # Did the fallback fail? Sigh, use the default.
+ # OpenTAL provides a default text.
+ # TAL doesn't but will use the default
+ # if None is returned
+ text = default
+
+ # Now we need to do the interpolation
+ text = self.interpolate(text, mapping)
+ return text
+
+ def negotiate_language(self, context, domain):
+ if context is None:
+ raise TypeError, 'No destination language'
+ else:
+ langs = [m[0] for m in catalogRegistry.keys() if m[1] == domain] +
\
+ [m[0] for m in fbcatalogRegistry.keys() if m[1] == domain]
+ for fallback in self._fallbacks:
+ if fallback not in langs:
+ langs.append(fallback)
+ target_language = self.negotiate(langs, context)
+ return target_language
+
+ def getDomain(self, domain):
+ """
+ """
+ return Domain(domain, self)
+
+ def interpolate(self, text, mapping):
+ try:
+ """Insert the data passed from mapping into the text"""
+
+ # If the mapping does not exist, make a "raw translation" without
+ # interpolation.
+ if mapping is None or type(text) not in (StringType, UnicodeType):
+ # silly wabbit!
+ return text
+
+ get = map_get
+ try:
+ mapping.get('')
+ except AttributeError:
+ get = getattr
+
+ # Find all the spots we want to substitute
+ to_replace = _interp_regex.findall(text)
+
+ # ZPT (string) or OpenPT (unicode)?
+ if type(text) is StringType:
+ conv = str
+ else:
+ conv = XML
+
+ # Now substitute with the variables in mapping
+ for string in to_replace:
+ var = _get_var_regex.findall(string)[0]
+ value = get(mapping, var)
+ try:
+ value = value()
+ except (TypeError, AttributeError):
+ pass
+ if value is None:
+ value = string
+ if type(value) not in (StringType, UnicodeType):
+ # FIXME: we shouldn't do this. We should instead
+ # return a list. But i'm not sure about how to use
+ # the regex to split the text.
+ value = conv(value)
+ text = text.replace(string, value)
+
+ return text
+ except:
+ import traceback
+ traceback.print_exc()
+
+ def manage_main(self, REQUEST, *a, **kw):
+ "Wrap Folder's manage_main to render international characters"
+ # ugh, API cruft
+ if REQUEST is self and a:
+ REQUEST = a[0]
+ a = a[1:]
+ r = Folder.manage_main(self, self, REQUEST, *a, **kw)
+ if type(r) is UnicodeType:
+ r = r.encode('utf-8')
+ REQUEST.RESPONSE.setHeader('Content-type', 'text/html; charset=utf-8')
+ return r
+
+ #
+ ############################################################
Index: opental/PlacelessTranslationService/__init__.py
diff -u /dev/null opental/PlacelessTranslationService/__init__.py:1.14.2.1
--- /dev/null Sun Sep 14 20:07:41 2003
+++ opental/PlacelessTranslationService/__init__.py Sun Sep 14 20:07:41 2003
@@ -0,0 +1,111 @@
+##############################################################################
+# Copyright (C) 2001, 2002, 2003 Lalo Martins <address@hidden>,
+# and Contributors
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+__version__ = '''
+$Id: __init__.py,v 1.14.2.1 2003/09/15 00:07:41 dreamcatcher Exp $
+'''.strip()
+
+from OFS.Application import get_products
+from AccessControl import ModuleSecurityInfo, allow_module, allow_class,
allow_type
+from PlacelessTranslationService import PlacelessTranslationService, log
+from Products.PageTemplates.GlobalTranslationService import
setGlobalTranslationService
+import os, fnmatch, zLOG, sys, Zope, Globals
+
+# in python 2.1 fnmatch doesn't have the filter function
+if not hasattr(fnmatch, 'filter'):
+ def fnfilter(names, pattern):
+ return [name for name in names if fnmatch.fnmatch(name, pattern)]
+ fnmatch.filter = fnfilter
+
+# patch flaky ZPT - this must be removed once someone fixes it
+# I'm leaving this enabled even for OpenPT, because it somehow manages
+# to make zope a bit faster...
+import PatchStringIO
+
+# this is for packages that need to initialize stuff after we're done
+notify_initialized = []
+
+# id to use in the Control Panel
+cp_id = 'TranslationService'
+
+# icon
+misc_ = {
+ 'PlacelessTranslationService.png':
+ Globals.ImageFile('www/PlacelessTranslationService.png', globals()),
+ 'GettextMessageCatalog.png':
+ Globals.ImageFile('www/GettextMessageCatalog.png', globals()),
+ }
+
+# import permissions
+security = ModuleSecurityInfo('Products.PlacelessTranslationService')
+security.declarePublic('negotiate')
+security.declarePublic('translate')
+security.declarePublic('getLanguages')
+security.declarePublic('getLanguageName')
+
+def make_translation_service(cp):
+ from Products import PlacelessTranslationService as pkg
+ # default (gettext) translation service
+ translation_service = PlacelessTranslationService('default')
+ translation_service.id = cp_id
+ cp._setObject(cp_id, translation_service)
+
+def initialize(context):
+ from Products import PlacelessTranslationService as pkg
+
+ # hook into the Control Panel
+ cp = context._ProductContext__app.Control_Panel # argh
+ if cp_id not in cp.objectIds():
+ make_translation_service(cp)
+ pkg.translation_service = getattr(cp, cp_id)
+
+ # don't touch - this is the last version
+ # that didn't have the attribute (0.4)
+ instance_version = getattr(translation_service, '_instance_version', (0,
4, 0, 0))
+ if instance_version < PlacelessTranslationService._class_version:
+ log('outdated translation service found, recreating',
+ detail = '(found %s.%s.%s.%s)\n' % instance_version)
+ cp._delObject(cp_id)
+ make_translation_service(cp)
+ pkg.translation_service = getattr(cp, cp_id)
+ ts_unwrapped = translation_service.aq_base
+
+ # set ZPT's translation service
+ setGlobalTranslationService(translation_service)
+
+ pkg.translate = translation_service.translate
+ pkg.getLanguages = translation_service.getLanguages
+ pkg.getLanguageName = translation_service.getLanguageName
+ pkg.negotiate = translation_service.negotiate
+
+ log('products: %r' % get_products(), zLOG.BLATHER)
+ # sweep products
+ for prod in get_products():
+ # prod is a tuple in the form:
+ #(priority, dir_name, index, base_dir) for each Product directory
+ ts_unwrapped._load_dir(os.path.join(prod[3], prod[1], 'i18n'))
+
+ # sweep the i18n directory for local catalogs
+ ts_unwrapped._load_dir(os.path.join(INSTANCE_HOME, 'i18n'))
+
+ # didn't found any catalogs
+ if not ts_unwrapped.objectIds():
+ log('no translations found!', zLOG.PROBLEM)
+
+ # notify anyone who needs it
+ for function in notify_initialized:
+ function()
- [OpenTAL-checkins] CVSROOT: /cvsroot/opental,
Sidnei da Silva <=