loops/i18n/common.py
helmutm 32ef1a067d bug fixes for import, i18n, actions
git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2437 fd906abe-77d9-0310-91a1-e0d9ade77398
2008-03-06 11:28:49 +00:00

149 lines
5 KiB
Python

#
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
#
# 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
#
"""
Common stuff.
$Id$
"""
from zope import component
from zope.component import adapts
from zope.interface import implements
from zope.cachedescriptors.property import Lazy
from zope.security.proxy import removeSecurityProxy
from persistent.mapping import PersistentMapping
from cybertools.typology.interfaces import IType
from loops.common import adapted, AdapterBase
_not_found = object()
# support for i18n content
class I18NValue(PersistentMapping):
""" A dictionary to be used for storing values for different languages.
"""
default = None
def lower(self):
# this should only be used as a fallback for the title attribute
return self.getDefault().lower()
def getDefault(self):
if self.default is None:
return self.values()[0]
return self.default
def __str__(self):
return str(self.getDefault())
#def __unicode__(self):
# return unicode(self.getDefault())
def __repr__(self):
return 'I18NValue(%r)' % dict(self)
def getI18nValue(obj, attr, langInfo=None):
obj = removeSecurityProxy(obj)
value = getattr(obj, attr, None)
if isinstance(value, I18NValue):
if langInfo:
result = value.get(langInfo.language, _not_found)
if result is _not_found and langInfo.allowDefault:
result = value.get(langInfo.defaultLanguage, _not_found)
if result is _not_found:
result = value.getDefault()
return result
else:
return value.getDefault()
if langInfo is None or langInfo.allowDefault:
return value
return None
def setI18nValue(obj, attr, value, langInfo=None):
obj = removeSecurityProxy(obj)
old = getattr(obj, attr, None)
if langInfo is None:
if isinstance(old, I18NValue):
# TODO (?): Just replace the value corresponding to
# that of the default language
raise ValueError('Attribute %s on object %s is an I18NValue (%s) '
'and no langInfo given.' % (attr, obj, value))
else:
setattr(obj, attr, value)
return
lang = langInfo.language
if isinstance(old, I18NValue):
old[lang] = value
else:
i18nValue = I18NValue(((lang, value),))
defaultLang = langInfo.defaultLanguage
if lang != defaultLang:
# keep existing value
i18nValue[defaultLang] = old
i18nValue.default = i18nValue[defaultLang]
setattr(obj, attr, i18nValue)
#print '*** setI18nValue', attr, langInfo, lang, value, getattr(obj, attr, None)
class I18NAdapterBase(AdapterBase):
""" Base (or mix-in) class for concept adapters for internationalization of
context attributes.
"""
_adapterAttributes = AdapterBase._adapterAttributes + ('languageInfo',)
languageInfo = None
@Lazy
def i18nAttributes(self):
if getattr(self.context, '__parent__', None) is None:
# temporary object during creation
return []
tp = IType(self.context)
attrs = tp.optionsDict.get('i18nattributes', '')
return [attr.strip() for attr in attrs.split(',')]
def __getattr__(self, attr):
self.checkAttr(attr)
langInfo = attr in self.i18nAttributes and self.languageInfo or None
return getI18nValue(self.context, '_' + attr, langInfo)
def __setattr__(self, attr, value):
if attr in self._adapterAttributes:
object.__setattr__(self, attr, value)
else:
langInfo = attr in self.i18nAttributes and self.languageInfo or None
self.checkAttr(attr)
setI18nValue(self.context, '_' + attr, value, langInfo)
def translations(self, attr='title', omitCurrent=True):
langInfo = self.languageInfo
if langInfo:
langs = langInfo.availableLanguages
if len(langs) > 1:
value = getattr(removeSecurityProxy(self.context), '_' + attr, None)
if isinstance(value, I18NValue):
result = dict((k, v) for k, v in value.items() if v)
if omitCurrent and langInfo.language in result:
del result[langInfo.language]
return result
return {}