Who this is for. The technical lead estimating or running a change of engine on an existing site, and the developers doing it. Afterwards you have an order of work that avoids the bugs ports usually ship with, and a way to estimate the job from the site's own templates rather than from a guess.
Two constraints that shape the job
- It ships all at once. The engine is one setting for the whole site,
Globals.template.engine, so there is no running half the templates in each. Port on a branch, deployed to a development environment whose.settings.jsonalready names the target engine, and release the port and the setting together. - Nothing outside
templates/changes. Layouts, areas, components, content, URLs and the front-end build are engine-independent (What is identical in both). Template code kept in the admin is the exception: it is rendered by the site's engine too, so it is part of the port.
The procedure
- Inventory the constructs. Count each construct in the equivalence table across the template set, and list the template code in jobs, discount conditions, shipping methods and the search facets template. The counts are the estimate (below).
- Keep every file name. Layouts name their templates as plain paths, so rename a file and every record on that layout breaks. Change the contents, never the path. Templates with a
-twigsuffix are the platform's own and are not a pattern to copy. - Escaping first. Carry every escape across exactly:
|escapebecomes|eand the reverse, with the same strategy. Add none and drop none because of the target engine: neither engine escapes on Core dna (Escaping). Remove|rawwhen porting to Smarty, which has no equivalent and needs none. - Translation second. The translation files stay as they are. To Twig, every
{'key'|_:'domain'},{_ key=…}and{__}…{/__}becomes a call to one macro over__.translate(); to Smarty, the macro calls become the|_modifier (Translating in Twig, Translating in Smarty). - Scope third. Find every
scope='parent',scope='root'andscope='global'and replace it with_templateContext, or the reverse. Then look at includes: a Smarty partial that relied on seeing its caller's variables needs them passed explicitly before you addonlyin Twig, and a Twig partial that relied ononlymay collide with its caller's variables in Smarty. - The platform helpers.
|formatbecomes|datewith the site's format from_config;{json}becomes a map and|json_encode;{error}has no Twig equivalent;{break}and{continue}become a filtered list; foreach properties becomeloop.*;{strip}becomes whitespace modifiers. In the other direction, Smarty needs its ternary conditions in parentheses and has no??. - The platform's own screens. Moving to Twig, override every platform template the site uses that exists only in Smarty, such as
users/login.html; otherwise it prints its Smarty source as text (Overriding a platform template). Moving to Smarty, a site's-twigoverrides stop being used and need Smarty versions under the plain names. - Verify by comparing rendered pages. Before the port, save the rendered HTML of a list of URLs covering every layout; after it, render the same URLs on the development environment and compare the text of each. A port that looks right can still have lost a heading level, doubled an escape or emptied a block. In Twig, an empty block where content was is the sign of a misspelt method.