Commit c60e89fe authored by Vincent Pelletier's avatar Vincent Pelletier

Do not modify portal type when viewing translation domains.

Based on a patch by Aurélien Calonne <aurel@nexedi.com>.
Also, cleanup TranslationProviderBase code a bit.
parent ff14027c
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
</item> </item>
<item> <item>
<key> <string>action</string> </key> <key> <string>action</string> </key>
<value> <string>Base_edit</string> </value> <value> <string>Base_editTranslationDomainList</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_body</string> </key>
<value> <string>def edit(url, edit_order, cleaned_v):\n
context.setTranslationDomain(url.split("/")[-1], cleaned_v[\'domain_name\'])\n
return context.Base_edit(form_id, listbox_edit=edit, *args, **kw)\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>form_id, *args, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_editTranslationDomainList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -11,163 +11,73 @@ ...@@ -11,163 +11,73 @@
# FOR A PARTICULAR PURPOSE # FOR A PARTICULAR PURPOSE
# #
############################################################################## ##############################################################################
from Products.ERP5Type.Globals import InitializeClass from Products.ERP5Type.Globals import InitializeClass
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.CMFCore.Expression import Expression from Permissions import AccessContentsInformation, ManagePortal, \
from Products.ERP5Type import _dtmldir ModifyPortalContent
from Products.ERP5Type.Cache import CachingMethod
from Permissions import AccessContentsInformation, ManagePortal, ModifyPortalContent
from OFS.SimpleItem import SimpleItem from OFS.SimpleItem import SimpleItem
from Products.ERP5Type import PropertySheet from Acquisition import aq_base
from Acquisition import aq_base, Implicit from Products.ERP5Type.Globals import PersistentMapping, Persistent
from Products.ERP5Type.Accessor.Translation import \
import Products TRANSLATION_DOMAIN_CONTENT_TRANSLATION
from Products.ERP5Type.Accessor import Translation
from zLOG import LOG
_MARKER = {}
class PropertyDomainDict(Implicit):
"""
Combined with TranslationProviderBase.property_domain_dict,
this class makes TranslationInformation objects inside
TranslationProviderBase._property_domain_dict accessible with
(un)restrictedTraverse. This hack allows forms to use Base_edit
for such objects.
"""
def _aq_dynamic(self, attr):
type_info = self.aq_parent
try:
return type_info._property_domain_dict[attr].__of__(type_info)
except KeyError:
return None
class TranslationProviderBase(object): class TranslationProviderBase(object):
""" """
Provide Translation Tabs and management methods for PropertyTranslationDomain Provide Translation Tabs and management methods for PropertyTranslationDomain
""" """
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declarePrivate('updateInitialPropertyTranslationDomainDict')
def updateInitialPropertyTranslationDomainDict(self):
"""
Updates the list of association between property and domain name.
This method must be called anytime new translatable properties are added.
"""
property_domain_dict = {}
for prop in self._getPropertyHolder().getAccessorHolderPropertyList():
prop_id = prop['id']
if prop.get('translatable') and prop_id not in property_domain_dict:
domain_name = prop.get('translation_domain')
property_domain_dict[prop_id] = TranslationInformation(prop_id,
domain_name)
original_property_domain_dict = getattr(aq_base(self),
'_property_domain_dict', _MARKER)
# Only update if required in order to prevent ZODB from growing
if original_property_domain_dict is _MARKER or\
sorted(property_domain_dict) != sorted(original_property_domain_dict):
# Update existing dict
property_domain_dict.update(original_property_domain_dict)
# And store
self._property_domain_dict = property_domain_dict
security.declareProtected(AccessContentsInformation, security.declareProtected(AccessContentsInformation,
'getPropertyTranslationDomainDict') 'getPropertyTranslationDomainDict')
def getPropertyTranslationDomainDict(self): def getPropertyTranslationDomainDict(self):
""" """
Return all translations defined by a provider. Return all translations defined by a provider.
""" """
# From time to time we'll update property translation domain dict. property_domain_dict = {}
def _updatePropertyTranslationDomainDict(): for prop in self._getPropertyHolder().getAccessorHolderPropertyList():
self.updateInitialPropertyTranslationDomainDict() if prop.get('translatable'):
CachingMethod(_updatePropertyTranslationDomainDict, prop_id = prop['id']
id='%s._updateInitialPropertyTranslationDomainDict' % self.getId(), property_domain_dict[prop_id] = TranslationInformation(
cache_factory='erp5_ui_long')() prop_id,
prop.get('translation_domain'),
if getattr(self, '_property_domain_dict', None) is None: )
return {} try:
my_property_domain_dict = aq_base(self)._property_domain_dict
except AttributeError:
pass
else: else:
return dict((k, v.__of__(self)) property_domain_dict.update(my_property_domain_dict)
for k, v in self._property_domain_dict.iteritems()) return dict((k, v.__of__(self))
for k, v in property_domain_dict.iteritems())
security.declarePublic('getContentTranslationDomainPropertyNameList') security.declarePublic('getContentTranslationDomainPropertyNameList')
def getContentTranslationDomainPropertyNameList(self): def getContentTranslationDomainPropertyNameList(self):
result = [] return [x for x, y in self.getPropertyTranslationDomainDict().iteritems()
for property_name, translation_information in self.getPropertyTranslationDomainDict().items(): if y.getDomainName() == TRANSLATION_DOMAIN_CONTENT_TRANSLATION]
if translation_information.getDomainName()==Translation.TRANSLATION_DOMAIN_CONTENT_TRANSLATION:
result.append(property_name)
return result
# security.declareProtected(ManagePortal, 'setTranslationDomain')
# ZMI methods def setTranslationDomain(self, prop_name, domain):
#
security.declareProtected(ManagePortal, 'manage_editTranslationForm')
def manage_editTranslationForm(self, REQUEST, manage_tabs_message=None):
""" Show the 'Translation' management tab.
""" """
translation_list = [] Set a translation domain for given property.
self.updateInitialPropertyTranslationDomainDict() # Force update in case of change of PS list
prop_domain_name_dict = self.getPropertyTranslationDomainDict()
keys = prop_domain_name_dict.keys()
keys.sort()
for k in keys:
prop = prop_domain_name_dict[k]
t = {}
t['property_name'] = prop.getPropertyName()
t['domain_name'] = prop.getDomainName()
translation_list.append(t)
# get a list of message catalogs and add empty one for no traduction and
# add another for content translation.
translation_domain_list = self.portal_property_sheets.getTranslationDomainNameList()
return self._translation_form( self
, REQUEST
, translations = translation_list
, possible_domain_names=translation_domain_list
, management_view='Translation'
, manage_tabs_message=manage_tabs_message
)
security.declareProtected(ManagePortal, 'changeTranslations')
def changeTranslations(self, properties=None, REQUEST=None):
""" """
Update our list of translations domain name try:
""" property_domain_dict = aq_base(self)._property_domain_dict
if properties is None: except AttributeError:
properties = REQUEST self._property_domain_dict = property_domain_dict = PersistentMapping()
else:
# PropertySheet might be changed. # BBB: If domain dict is not a stand-alone peristent object, changes made
self.updateInitialPropertyTranslationDomainDict() # to it won't be persistently stored. It used to work because the whole
# dict was replaced, hence triggering a change on self. But this creates
property_domain_dict = self.getPropertyTranslationDomainDict() # an inconvenient API. For the sake of keeping BT diffs quiet, don't cast
for prop_name in property_domain_dict.keys(): # that dict into a PersistentMapping.
new_domain_name = properties.get(prop_name) if not isinstance(property_domain_dict, Persistent):
prop_object = property_domain_dict[prop_name] self._p_changed = 1
if new_domain_name != prop_object.getDomainName(): property_domain_dict[prop_name] = TranslationInformation(prop_name, domain)
prop_object.edit(domain_name=new_domain_name)
# Reset accessor cache # Reset accessor cache
types_tool = self.getPortalObject().portal_types self.getPortalObject().portal_types.\
types_tool.resetDynamicDocumentsOnceAtTransactionBoundary() resetDynamicDocumentsOnceAtTransactionBoundary()
if REQUEST is not None:
return self.manage_editTranslationForm(REQUEST, manage_tabs_message=
'Translations Updated.')
security.declareProtected(ModifyPortalContent, 'property_domain_dict')
@property
def property_domain_dict(self):
return PropertyDomainDict().__of__(self)
InitializeClass(TranslationProviderBase)
class TranslationInformation(SimpleItem): class TranslationInformation(SimpleItem):
""" """
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment