opental-checkins
[Top][All Lists]
Advanced

[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')




reply via email to

[Prev in Thread] Current Thread [Next in Thread]