Message.py 7.42 KB
Newer Older
1 2 3
##############################################################################
#
# Copyright (c) 2006 Nexedi SARL and Contributors. All Rights Reserved.
4
#                    Aurelien Calonne <aurel@nexedi.com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# 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.
#
##############################################################################

29
from Products.ERP5Type.Globals import InitializeClass, Persistent
30 31
from AccessControl import ClassSecurityInfo
from Products.PythonScripts.Utility import allow_class
32
try:
33 34
  from Products.PageTemplates.GlobalTranslationService import getGlobalTranslationService
  # on Zope 2.8
35
except ImportError:
36
  # on Zope 2.12, though we should try to see if it works on 2.8 as well
37 38
  import zLOG, sys
  zLOG.LOG('Products.ERP5Type.Messages',
39
      zLOG.INFO,
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
      'Products.PageTemplates.GlobalTranslationService has been removed. '
      'Using alternative implementation',)
  import zope.i18n
  from zope.i18n.interfaces import ITranslationDomain
  from Acquisition import aq_get

  class GlobalTranslationService(object):
    """ GlobalTranslationService replacement """
    # inspired by the old Localizer GlobalTranslationService 

    def getTranslateMethod(self, context, domain):
        """Returns either the translate() method of an appropriate Localizer
        MessageCatalog or zope.i18n.translate
        """
        if context is None:
            return zope.i18n.translate
        # Try to get a catalog from a Localizer Object using acquisition
        # FIXME: This should be fixed to use queryUtility instead, but only
        # after ERP5Site starts implementing ISite so that MessageCatalogs can
        # registerm themselves as local utilities.
        # translation_domain = zope.component.getUtility(ITranslationDomain,
        #                                                domain,
        #                                                context=context)
        translation_domain = context.unrestrictedTraverse(("Localizer", domain),
                                                          None)
        # FIXME: Remove this check once we're using getUtility
        if ITranslationDomain.providedBy(translation_domain):
            return translation_domain.translate
68 69 70 71 72
        # Localizer above does not like the 'domain' keyword, but zope.i18n
        # needs it.
        def translate(**kw):
          return zope.i18n.translate(domain=domain, **kw)
        return translate
73 74 75

    def translate(self, domain, msgid, context=None, **kw):
        translate = self.getTranslateMethod(context, domain)
76
        
77 78 79 80 81 82
        # For zope.i18n, the 'context' of a translation request is actually the
        # an IBrowserRequest, for languate negotiation (see, for instance,
        # Products.CMFPlone.TranslationServiceTool). The new localizer
        # MessageCatalog abides by the zope.i18n.interface definitions.
        # (Actually, it ignores the context).
        request = aq_get(context, 'REQUEST', None)
83
        return translate(msgid=msgid, context=request, **kw)
84 85 86

  getGlobalTranslationService = GlobalTranslationService

87
from Products.ERP5Type import Globals
88 89 90 91 92 93 94
from cPickle import dumps, loads

try:
  from string import Template
except ImportError:
  from Products.ERP5Type.patches.string import Template

95
from base64 import b64encode, b64decode
96 97 98 99 100 101 102 103 104

class Message(Persistent):
  """
  This class encapsulates message, mapping and domain for a given message
  """

  security = ClassSecurityInfo()
  security.declareObjectPublic()

105 106
  def __init__(self, domain=None, message='',
               mapping=None, default=None):
107 108 109
    self.message = message
    self.mapping = mapping
    self.domain = domain
110 111
    if default is None:
      default = message
112
    self.default = default
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129

  security.declarePublic('dump')
  def dump(self):
    """
    Return a pickle version of the object
    """
    return b64encode(dumps(self, 2))

  security.declarePublic('load')
  def load(self, string):
    """
    Get properties from pickle version
    """
    o = loads(b64decode(string))
    self.message = o.message
    self.domain = o.domain
    self.mapping = o.mapping
130
    self.default = o.default
131

132
  def translate(self):
133
    """
134 135 136
    Return the translated message. If the original is a string object,
    the return value is a string object. If it is a unicode object,
    the return value is a unicode object.
137
    """
138
    message = self.message
139
    if self.domain is None:
140
      # Map the translated string with given parameters
141
      if type(self.mapping) is dict:
142
        if isinstance(message, unicode) :
143
          message = message.encode('utf-8')
144
        message = Template(message).substitute(self.mapping)
145
    else:
146
      from Products.ERP5.ERP5Site import getSite
147
      request = Globals.get_request()
148
      translation_service = getGlobalTranslationService()
149 150 151 152 153 154 155 156
      if self.mapping:
        unicode_mapping = {}
        for k, v in self.mapping.iteritems():
          if isinstance(v, str):
            v = v.decode('utf-8')
          unicode_mapping[k] = v
      else:
        unicode_mapping = self.mapping
157
      translated_message = translation_service.translate(
158
                                             self.domain,
159
                                             message,
160
                                             mapping=unicode_mapping,
161
                                             context=getSite(request),
162 163
                                             default=self.default)
      if translated_message is not None:
164 165
        message = translated_message

166 167 168 169
    if isinstance(self.message, str):
      if isinstance(message, unicode):
        message = message.encode('utf-8')
    elif isinstance(message, str):
170 171 172 173
      message = message.decode('utf-8')

    return message

174 175 176
  def __repr__(self):
    return "<ERP5Type.Message.Message for %r>" % self.message

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
  def __str__(self):
    """
    Return the translated message as a string object.
    """
    message = self.translate()
    if isinstance(message, unicode):
      message = message.encode('utf-8')
    return message

  def __unicode__(self):
    """
    Return the translated message as a unicode object.
    """
    message = self.translate()
    if isinstance(message, str):
      message = message.decode('utf-8')
    return message
194

195 196 197 198 199 200 201 202 203
  def __len__(self):
    return len(str(self))

  def __getitem__(self, index):
    return str(self)[index]

  def __getslice__(self, i, j):
    return str(self)[i:j]

204 205
InitializeClass(Message)
allow_class(Message)
206 207 208 209


def translateString(message, **kw):
  return Message(domain='erp5_ui', message=message, **kw)