render()
The one way a registered template becomes text. render() is a pure function of template, context and registry state — no request faking, no site, no database. Previews, golden-file tests and the Email builder all go through this same door.
from imio.emailkit import render
html, text = render(
"imio.pm.notifications:item_published",
context={"item": item, "meeting": meeting},
language="fr",
)
Signature
- Name
name- Type
- str
- Description
The namespaced template name, e.g.
"imio.emailkit:notification". RaisesTemplateNotFoundif nothing is registered under it — carrying the list of names that are registered.
- Name
context- Type
- mapping, optional
- Description
Injected into the template namespace as top-level names, so a template reads
${item/title}and not${options/item}.
- Name
language- Type
- str, optional
- Description
The language to render in. Defaults to the negotiated language.
Returns a (html, text) tuple.
What ends up in the namespace
Precedence runs low to high: the registration's preheader, then your context, then the names the package injects. The injected names win — a caller who shadowed theme or lang would break the shell, not just their own template.
- Name
lang- Type
- str
- Description
The render language. The kit layout emits it on
<html>, so screen readers pick the right pronunciation.
- Name
theme- Type
- mapping
- Description
logo_url,primary_color,footer_html, read fromplone.app.registry. A missing registry, a missing record andNoneall collapse to the empty string — the string"None"in a mail is worse than nothing.
- Name
preheader- Type
- str
- Description
The translated
preheadermsgid from the registration, if the template declared one. Rendered into the layout's hidden div.
- Name
portal_url- Type
- str
- Description
The portal's absolute URL, or
""when there is no request to build one from.
- Name
translate- Type
- callable
- Description
Translates a msgid into the render language.
- Name
format_date, format_datetime, format_number- Type
- callables
- Description
Locale-aware formatting, already bound to the render language. See the helpers.
- Name
target_language- Type
- str
- Description
Zope's page-template i18n machinery reads the render language from this name. Without it,
i18n:translatenegotiates from the request — that is, renders the wrong language, silently, wheneverlanguagewas passed explicitly.
Locale helpers
Three callables, bound to the render language, so no template reinvents French date formatting — and half of them would get it wrong.
<td>${python: format_date(item.effective)}</td>
<td>${python: format_datetime(meeting.date)}</td>
<td>${python: format_number(amount)}</td>
| Helper | fr | en |
|---|---|---|
format_date(value) | 12 août 2026 | August 12, 2026 |
format_datetime(value) | 12 août 2026 17:30 | August 12, 2026 5:30 PM |
format_number(value) | 1 234,5 | 1,234.5 |
format_date and format_datetime take an optional length; format_datetime also takes time_length; format_number takes a pattern.
Use python:, not a path. TAL path expressions cannot call functions: $ {format_date(when)} raises "Invalid variable name" when Chameleon compiles
the .pt. The python: prefix is what makes it an expression rather than a
path. The authoring lint catches this as path-call.
The plaintext part
If the template ships a hand-authored <name>.txt.pt twin, that is what you get. Without one, render() falls back to a naive text extraction of the HTML and logs a deprecation.
The twin is hand-authored on purpose. Maizzle's own plaintext output destroys tal: and i18n: constructs, so generating it would ship a plausible-looking body carrying the wrong content in the wrong language. See Testing.
Escaping
${...} values are HTML-escaped by Chameleon by default, which is the safe behaviour and the one you want. structure — unescaped insertion — is reserved for exactly two places: the shell's body_html slot and the footer_html theme token. Nothing else.
Related
- Email builder — what you almost always want instead, if you are sending rather than inspecting.
- render_shell() — the sibling for bodies that already exist.
- Errors —
TemplateNotFoundand what it carries. - Source:
imio/emailkit/render.py