Error translation, Multilingual "Could not adapt"

We have a folderish item, defined as dexterity schema. This container has a behaviour: when it's created it listens the event of "IObjectAddedEvent" and reproduces a structure of items inside itself from an attribute defined at the contenttype content.py.
It's just a contenttype which creates inner items when it's create (at IObjectAddedEvent).

It works great with one language, but when the created object gets translated it fires again the event IObjectAddedEvent (as expected, because it's creating a new object), but the problem comes when it tries to create the inner items at the translated container, and we get the following exception:

('Could not adapt', <Folder at /fs-storage/Test/es/esp-8/banners>, <SchemaClass contenttype.minisite.interfaces.IMinisite>)

Minisite is the contenttype which creates the inner folders, and banners is one of the folders being created inside it.
The error comes from the line where api.content.create executes container.invokeFactory at plone.api.content.py

Here is the script that is executed at the event IObjectAddedEvent

def create_inner_items(context, event):
  print "\n\nCreating (" + str(len(context.structure)) + ") inner item(s):"
  lang = api.portal.get_current_language() or api.portal.get_default_language()

  for kwargs_child in context.structure:
    normalizer = getUtility(IIDNormalizer)
    kwargs_child['title'] = api.portal.translate(kwargs_child['title'], domain=getattr(context, 'domain', None), lang=context.Language() or lang)
    _id = kwargs_child.get('id', normalizer.normalize(kwargs_child['title']))

    if not context.has_key(_id):
      print "\nCreating child " + kwargs_child['title'] + "..."

      try:
        kwargs_child['container'] = context
        kwargs_child['id'] = _id

        child_item = api.content.create( **kwargs_child )
        api.content.transition(obj=child_item, transition='publish')

        print "Item creatted properly: " + str(child_item)

        if kwargs_child.get('childs', False):
          child_item.structure = kwargs_child['childs']
          if hasattr(context, 'domain'):
            child_item.domain = context.domain

          create_inner_items(child_item, event)

      except Exception as e:
        import sys, os

        exc_type, exc_obj, exc_tb = sys.exc_info()
        fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]

        print "An error occurred while creating inner folders:\n" + str(e)
        print(exc_type, fname, exc_tb.tb_lineno)

        continue

    else:
      print kwargs_child['title'] + " already exists."
  return context

context.structure is the attribute where the structure of the inner items is defined, it looks like this:

@implementer(IMinisite)
class Minisite(Container):
  """Convenience subclass for ``Minisite`` portal type"""
  translating = False
  domain = 'contenttype.minisite'
  structure = [
    {
      'title': _(u"News"),
      'type': 'Folder',
      'exclude_from_nav': False,
      'constrain_types_mode': True,
      'locally_allowed_types': ["News Item"],
      'immediately_addable_types': ["News Item"],
    },
    {
      'title': _(u"Events"),
      'type': 'Folder',
      'exclude_from_nav': False,
      'constrain_types_mode': True,
      'locally_allowed_types': ["Event"],
      'immediately_addable_types': ["Event"],
    },
    {
      'title': _(u"Banners"),
      'type': 'Folder',
      'exclude_from_nav': True,
      'constrain_types_mode': True,
      'locally_allowed_types': ["Banner"],
      'immediately_addable_types': ["Banner"],
    }
  ]

the error you're describing sounds to me you're trying to create content on the wrong context.

one of the very first things you have to do on any event subscriber is to check if you're on the right context because, as you already mentioned, the IObjectAddedEvent will be fired multiple times in your case.

writing tests could be very useful in your case; check collective.fingerpointing for an example of such tests.

1 Like