# # 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(',')] # new implementation: # return self.options.i18n.attributes 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.startswith('__') or 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 {}