==================== Internationalization ==================== Forms are fully internationalized. The field names, descriptions, labels, and hints are all automatically translated if they are made i18n messages in the schema. Let's take this simple add form... >>> print http(r""" ... GET /addfieldcontent.html HTTP/1.1 ... """, handle_errors=False) HTTP/1.1 200 OK ... with an error... >>> print http(r""" ... POST /addfieldcontent.html HTTP/1.1 ... Content-Length: 670 ... Content-Type: multipart/form-data; boundary=---------------------------19588947601368617292863650127 ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.title" ... ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.description" ... ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.somenumber" ... ... 0 ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="UPDATE_SUBMIT" ... ... Hinzufxgen ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="add_input_name" ... ... ... -----------------------------19588947601368617292863650127-- ... """, handle_errors=False) HTTP/1.1 200 OK ... There are 1 input errors. ... Translated ========== And now the add form in German: >>> print http(r""" ... GET /addfieldcontent.html HTTP/1.1 ... Accept-Language: de ... """, handle_errors=False) HTTP/1.1 200 OK ...Felderinhalt hinzuf... ...Eine kurz...Titel... ...Eine ausf...Beschreibung... ...Irgendeine Zahl... ...Irgendeine Liste... The same with an input error: >>> print http(r""" ... POST /addfieldcontent.html HTTP/1.1 ... Accept-Language: de ... Content-Length: 670 ... Content-Type: multipart/form-data; boundary=---------------------------19588947601368617292863650127 ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.title" ... ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.description" ... ... ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="field.somenumber" ... ... 0 ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="UPDATE_SUBMIT" ... ... Hinzufxgen ... -----------------------------19588947601368617292863650127 ... Content-Disposition: form-data; name="add_input_name" ... ... ... -----------------------------19588947601368617292863650127-- ... """, handle_errors=False) HTTP/1.1 200 OK ...Felderinhalt hinzuf... ...1... ...Eine kurz...Titel... ...Eine ausf...Beschreibung... ...Irgendeine Zahl... Source widgets ============== Titles of terms are translated by the source widgets. Let's create a source for which the terms create message ids: >>> import zc.sourcefactory.basic >>> from zope.i18nmessageid import MessageFactory >>> _ = MessageFactory('coffee') >>> class Coffees(zc.sourcefactory.basic.BasicSourceFactory): ... def getValues(self): ... return ['arabica', 'robusta', 'liberica', 'excelsa'] ... def getTitle(self, value): ... return _(value, default='Translated %s' % value) >>> import zope.schema >>> from zope.publisher.browser import TestRequest >>> coffee = zope.schema.Choice( ... __name__ = 'coffee', ... title=u"Kinds of coffee beans", ... source=Coffees()) >>> request = TestRequest() >>> import zope.formlib.source >>> widget = zope.formlib.source.SourceDisplayWidget( ... coffee, coffee.source, request) >>> print widget() Nothing >>> from zope.formlib.interfaces import IBrowserWidget >>> IBrowserWidget.providedBy(widget) True >>> widget.setRenderedValue('arabica') >>> print widget() Translated arabica