How to translate a default value on Dexterity schemas

I have a z3c.form based control panel configlet and I need to initialize one of the fieds to a default the is language-dependent.

class IDisclaimerSettings(model.Schema):

    foo = schema.TextLine(
        title=_('title_foo', default=u'Foo'),

the issue I'm facing is the following:

  • if I use _(u'Bar') as default value, it works like charm and the translated string for u'Bar' is used
  • if I set a MessageID with a default value like _(u'default_foo', default=u'Bar'), it results on u'default_foo' instead of the translated string

I really want to use a MessageID in this case because the default value is a whole paragraph in HTML format.

any hints?

I've had issues like this before, don't quote me but it may be because the title attribute is translated when the view is rendered, at this time it has the request and can use the language negotiation.
If the the default value returns the ID this is indicative of the translation object not having a language accessible, I think...

Have you tried forcing a translation similarly to this then..?

from zope.i18n import translate
my_translated_string = translate(_(u'default_foo', default=u'Bar'), target_language='de')

I tried using plone.api.portal.translate but the result was the same.

Alright then the next step I'd do is write a widget method which when run fetches the current language of the context, translates the string and passes into the field.

Your observation is surprising: your first case indicates that the default value is translated, your second one that is is not translated; however, the difference is only in internals for the translation process itself.

To get control over that handling, I would not use the static defaultbut defaultFactory which allows to dynamically compute the default value. There, you could explicitly translate the value.

I had tested that before and it doesn't work.

I just tested that also and it doesn't work neither:

class DisclaimerSettingsEditForm(controlpanel.RegistryEditForm):
    schema = IDisclaimerSettings
    label = _(u'Disclaimer')

    def updateFields(self):
        super(DisclaimerSettingsEditForm, self).updateFields()
        self.fields['title'].field.default = _(u'default_foo', default=u'Bar')

results in u'default_foo' also.

I'm just giving up for now; I have more important things to do like implementing the features of the new package.

Sorry, I'm a bit late to this thread. I don't intend to dig the rabbit hole deeper, but I might do. :stuck_out_tongue: Reading this reminds me of an issue I tried to solve with @mauritsvanrees last year where I wanted a pre-translated portlet title.

plone.api's translate is (or at least was) not a functional equivalent of zope.i18n's translate. See this rather long issue thread if you really want to find out:

If you want to use defaultFactory and zope.i18n translate, you can inject a translation context, which actually is the request, which you can get from the context... From above discussion on the plone.api issue:

from zope.schema.interfaces import IContextAwareDefaultFactory

def translate_header(context):
    # use zope.i18n translate and pass in the request as the translation context
    return translate(_(u"Recently Updated Indicators"), context=context.REQUEST) 

class IRecentIndicatorsPortlet(IPortletDataProvider):

    header = schema.TextLine(title=_("Title"),

I was just looking up the ContextAwareDefault-blah for this post and I found the following snippet in collective.easyform. @hvelarde, maybe this helps with using a message label?

class IEasyFormImportFormSchema(Interface):
    """Schema for easyform import form.
    upload = Bytes(

def default_submitLabel(context):
    return translate(
    foo = _(u'default_submitLabel', u'Submit')  # dummy msgid for i18ndude to translate  # noqa
1 Like

thank you, very much! I was suspecting the request was involved but I had no idea on how to solve it.

Plone Foundation Code of Conduct