[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[OpenTAL-checkins] opental/PlacelessTranslationService GettextMess...
From: |
Fernando Lalo Martins |
Subject: |
[OpenTAL-checkins] opental/PlacelessTranslationService GettextMess... |
Date: |
Thu, 27 Feb 2003 20:37:44 -0500 |
CVSROOT: /cvsroot/opental
Module name: opental
Changes by: Fernando Lalo Martins <address@hidden> 03/02/27 20:37:44
Modified files:
PlacelessTranslationService: GettextMessageCatalog.py
PlacelessTranslationService.py
__init__.py
Log message:
PlacelessTranslationService now has an UI in the Control Panel
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/GettextMessageCatalog.py.diff?tr1=1.5&tr2=1.6&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/PlacelessTranslationService.py.diff?tr1=1.12&tr2=1.13&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/opental/opental/PlacelessTranslationService/__init__.py.diff?tr1=1.5&tr2=1.6&r1=text&r2=text
Patches:
Index: opental/PlacelessTranslationService/GettextMessageCatalog.py
diff -u opental/PlacelessTranslationService/GettextMessageCatalog.py:1.5
opental/PlacelessTranslationService/GettextMessageCatalog.py:1.6
--- opental/PlacelessTranslationService/GettextMessageCatalog.py:1.5 Fri Feb
21 18:29:40 2003
+++ opental/PlacelessTranslationService/GettextMessageCatalog.py Thu Feb
27 20:37:43 2003
@@ -17,13 +17,24 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
"""A simple implementation of a Message Catalog.
-$Id: GettextMessageCatalog.py,v 1.5 2003/02/21 23:29:40 lalo Exp $
+$Id: GettextMessageCatalog.py,v 1.6 2003/02/28 01:37:43 lalo Exp $
"""
from gettext import GNUTranslations
import os
import 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
+
+try:
+ from Products.OpenPT.OpenPTFile import OpenPTFile as ptFile
+except ImportError:
+ #FIXME: ZPT
+ ptFile = None
# template to use to write missing entries to .missing
missing_template = u"""msgid "%(id)s"
@@ -36,16 +47,24 @@
orig_text_line_joiner = u"\n#. "
-class GettextMessageCatalog:
- """ """
+permission = 'View management screens'
+
+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',)
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.__translation_object = None
self._prepareTranslations()
-
def _prepareTranslations(self):
""" """
if self.__translation_object is None:
@@ -54,42 +73,64 @@
file.close()
self._language = (tro._info.get('language-code', None) # new way
or tro._info.get('language', None)) # old way
+ self._language = self._language.lower().replace('_', '-')
self._domain = tro._info.get('domain', None)
if self._language is None or self._domain is None:
raise ValueError, 'potfile has no metadata'
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
self.__translation_object = tro
- missing = self._path_to_file[:-1] + 'issing'
- if os.access(missing, os.W_OK):
- self.__missing = codecs.open(missing, 'a',
-
self.__translation_object._charset)
+ self._missing = self._path_to_file[:-1] + 'issing'
+ if not os.access(self._missing, os.W_OK):
+ self._v_missing = None
+ if self.name:
+ self.title = '%s language (%s) for %s' % (self._language,
self.name, self._domain)
else:
- self.__missing = None
-
+ 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"
+ self.__translation_object = None
+ 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.__translation_object._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):
+ def getMessage(self, id, orig_text=None, testing=False):
"""
"""
self._prepareTranslations()
msg = self.__translation_object.gettext(id)
if msg is id:
- if self.__missing:
- if orig_text:
- orig_text =
orig_text_line_joiner.join(orig_text.split('\n'))
- self.__missing.write(orig_text_template % {'text':
orig_text})
- self.__missing.write(missing_template % {'id':id.replace('"',
r'\"')})
- self.__missing.flush()
+ if not testing:
+ self._log_missing(id, orig_text)
raise KeyError
if type(msg) is StringType:
msg = unicode(msg, self.__translation_object._charset)
return msg
+ queryMessage__roles__=None # Public
def queryMessage(self, id, default=None):
"""
"""
try:
- return self.getMessage(id, default)
+ return self.getMessage(id, default, testing=True)
except KeyError:
if default is None:
default = id
@@ -100,6 +141,11 @@
"""
return self._language
+ def getLanguageName(self):
+ """
+ """
+ return self.name or self._language
+
def getDomain(self):
"""
"""
@@ -108,12 +154,48 @@
def getIdentifier(self):
"""
"""
- return self._path_to_file
+ return self.id
+
+ def getId(self):
+ """
+ """
+ return self.id
def getInfo(self, name):
"""
"""
return self.__translation_object._info.get(name, None)
-
+
+ ############################################################
+ # 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')
+
+ def file_exists(self):
+ try:
+ file = open(self._path_to_file, 'rb')
+ except:
+ return False
+ return True
+
+ def displayInfo(self):
+ self._prepareTranslations()
+ info = self.__translation_object._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 opental/PlacelessTranslationService/PlacelessTranslationService.py:1.12
opental/PlacelessTranslationService/PlacelessTranslationService.py:1.13
--- opental/PlacelessTranslationService/PlacelessTranslationService.py:1.12
Thu Feb 27 14:04:50 2003
+++ opental/PlacelessTranslationService/PlacelessTranslationService.py Thu Feb
27 20:37:43 2003
@@ -17,10 +17,11 @@
# 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.12 2003/02/27 19:04:50 lalo Exp $
+$Id: PlacelessTranslationService.py,v 1.13 2003/02/28 01:37:43 lalo Exp $
"""
-import re, zLOG
+import re, zLOG, Globals
+from OFS.Folder import Folder
from types import DictType, StringType, UnicodeType
from Negotiator import negotiator
from Domain import Domain
@@ -55,31 +56,47 @@
LANGUAGE_FALLBACKS = list(os.environ.get('LANGUAGE_FALLBACKS', 'en').split('
'))
-class PlacelessTranslationService:
+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, 4, 0, 4)
+ all_meta_types = ()
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 IMessageCatalog instances
+ # _catalogs maps (language, domain) to identifiers
self._catalogs = {}
- # _data maps IMessageCatalog.getIdentifier() to IMessageCatalog
- self._data = {}
# 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
+ # Disable some inappropriate operations
+ manage_addObject=None
+ manage_delObjects=None
+ manage_addProperty=None
+ manage_editProperties=None
+ manage_delProperties=None
+
def _registerMessageCatalog(self, language, domain, catalog_name):
http_language = language.lower().replace('_', '-')
key = (http_language, domain)
mc = self._catalogs.setdefault(key, [])
mc.append(catalog_name)
- log('adding catalog for domain %s, language %s' % (domain, language))
def addCatalog(self, catalog):
- self._data[catalog.getIdentifier()] = 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.getLanguage(),
catalog.getDomain(),
catalog.getIdentifier())
@@ -94,7 +111,7 @@
for (ccode, cdomain), cnames in self._catalogs.items():
if ccode == code:
for cname in cnames:
- cat = self._data[cname]
+ cat = self._getOb(cname)
if cat.name:
return cat.name
@@ -149,7 +166,7 @@
break
for name in catalog_names:
- catalog = self._data[name]
+ catalog = self._getOb(name)
try:
text = catalog.getMessage(msgid, default)
except KeyError:
Index: opental/PlacelessTranslationService/__init__.py
diff -u opental/PlacelessTranslationService/__init__.py:1.5
opental/PlacelessTranslationService/__init__.py:1.6
--- opental/PlacelessTranslationService/__init__.py:1.5 Fri Feb 21 18:29:40 2003
+++ opental/PlacelessTranslationService/__init__.py Thu Feb 27 20:37:43 2003
@@ -16,7 +16,7 @@
# 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.5 2003/02/21 23:29:40 lalo Exp $
+$Id: __init__.py,v 1.6 2003/02/28 01:37:43 lalo Exp $
'''.strip()
from AccessControl import ModuleSecurityInfo, allow_module, allow_class,
allow_type
@@ -24,39 +24,79 @@
from Negotiator import negotiate
from GettextMessageCatalog import GettextMessageCatalog
from Products.PageTemplates.GlobalTranslationService import
setGlobalTranslationService
-import os, glob, zLOG, sys
+import os, fnmatch, zLOG, sys, Zope, Globals
# 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
-# default (gettext) translation service
-translation_service = PlacelessTranslationService('default')
-# set the translation service
-setGlobalTranslationService(translation_service)
-
-translate = translation_service.translate
-getLanguages = translation_service.getLanguages
-getLanguageName = translation_service.getLanguageName
-
-security = ModuleSecurityInfo('Products.PlacelessTranslationService')
-security.declarePublic('negotiate')
-security.declarePublic('translate')
-security.declarePublic('getLanguages')
-security.declarePublic('getLanguageName')
-
-# sweep the i18n directory
-basepath = os.path.join(INSTANCE_HOME, 'i18n')
-if os.path.isdir(basepath):
- names = glob.glob(os.path.join(basepath, '*.mo'))
- if not names:
- log('no translations found!', zLOG.PROBLEM)
- for name in names:
- try:
- translation_service.addCatalog(GettextMessageCatalog(name))
- 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())
+# 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()),
+ }
+
+_marker = []
+
+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):
- pass
+ from Products import PlacelessTranslationService as pkg
+
+ # hook into the Control Panel
+ cp = Zope.app().Control_Panel
+ if cp_id not in cp.objectIds():
+ make_translation_service(cpl)
+ pkg.translation_service = getattr(cp, cp_id)
+
+ 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
+
+ security = ModuleSecurityInfo('Products.PlacelessTranslationService')
+ security.declarePublic('negotiate')
+ security.declarePublic('translate')
+ security.declarePublic('getLanguages')
+ security.declarePublic('getLanguageName')
+
+ # sweep the i18n directory
+ basepath = os.path.join(INSTANCE_HOME, 'i18n')
+ if os.path.isdir(basepath):
+ names = fnmatch.filter(os.listdir(basepath), '*.mo')
+ if not names:
+ log('no translations found!', zLOG.PROBLEM)
+ for name in names:
+ ob = ts_unwrapped._getOb(name, _marker)
+ try:
+ if ob is _marker:
+
translation_service.addCatalog(GettextMessageCatalog(os.path.join(basepath,
name)))
+ else:
+ ob.reload()
+ 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(translation_service.objectIds()) +
'\n')