2026 Community Survey results are here! See how the Craft CMS community works. results are live!

Common Pitfalls & Wrap-up

Practical advice on avoiding common mistakes when internationalizing Craft CMS projects, including when to use translations versus CMS content, why placeholders matter, and how to handle HTML within translated strings.

Let’s wrap up the course with some prac­ti­cal advice on avoid­ing com­mon mis­takes when inter­na­tion­al­iz­ing Craft CMS projects, includ­ing when to use trans­la­tions ver­sus CMS con­tent, why place­hold­ers mat­ter, and how to han­dle HTML with­in trans­lat­ed strings.

One of the most impor­tant deci­sions in any mul­ti­lin­gual Craft CMS project is know­ing when to use trans­la­tions ver­sus CMS con­tent. Trans­la­tions live in PHP source files and are not editable by con­tent authors, which makes them ide­al for UI strings that require place­hold­ers, for­mat­ting log­ic, or plu­ral­iza­tion rules. How­ev­er, con­tent like page head­lines is often bet­ter served as a CMS field so that edi­tors can cus­tomize and opti­mize it for SEO. A good rule of thumb is that if the string is a UI label or involves dynam­ic for­mat­ting, use a trans­la­tion. If it is edi­to­r­i­al con­tent that edi­tors should be able to change, put it in the con­trol pan­el as a field.

A very com­mon mis­take in plu­g­ins and projects is con­cate­nat­ing trans­lat­ed pre­fix­es or suf­fix­es with dynam­ic val­ues instead of using place­hold­ers. For exam­ple, trans­lat­ing Pub­lished on” as a stand­alone string and then append­ing a date after it works fine in Eng­lish, but it locks the date into a fixed posi­tion with­in the sen­tence. Oth­er lan­guages may need the date at the begin­ning, in the mid­dle, or for­mat­ted dif­fer­ent­ly. By hard-cod­ing the posi­tion, you force trans­la­tors into a sen­tence struc­ture that may be awk­ward or gram­mat­i­cal­ly incor­rect in their lan­guage. The solu­tion is to always pass dynam­ic val­ues as place­hold­ers with­in the full trans­lat­ed string. This gives trans­la­tors com­plete con­trol over where each val­ue appears, and they can even omit para­me­ters entire­ly if their lan­guage does not need them.

Mix­ing HTML with trans­la­tions intro­duces its own chal­lenges. If you need seman­tic markup like a <time> ele­ment inside a trans­lat­ed string, you must use the |raw fil­ter in Twig to pre­vent the HTML from being escaped. This works safe­ly when the para­me­ters are known safe val­ues like dates, but it cre­ates a cross-site script­ing vul­ner­a­bil­i­ty if any user-pro­vid­ed data is passed through. Exter­nal trans­la­tors may also strug­gle with HTML syn­tax in trans­la­tion strings. Alter­na­tive approach­es include prepar­ing the HTML sep­a­rate­ly and pass­ing it as a para­me­ter, or split­ting the trans­la­tion into parts, though both sac­ri­fice some flex­i­bil­i­ty. There is no per­fect solu­tion, so you need to weigh the trade-offs between seman­tic cor­rect­ness, trans­la­tor expe­ri­ence, secu­ri­ty, and the abil­i­ty to cus­tomize for­mat­ting per language.

Key Take­aways #

  • Use trans­la­tions for UI strings with place­hold­ers and for­mat­ting log­ic. Use CMS fields for edi­to­r­i­al con­tent that edi­tors need to control
  • Nev­er con­cate­nate trans­lat­ed pre­fix­es or suf­fix­es with dynam­ic val­ues. Always use place­hold­ers so trans­la­tors can repo­si­tion or omit them
  • Pass all poten­tial­ly use­ful para­me­ters to your trans­la­tions, even if your pri­ma­ry lan­guage does not use all of them, so oth­er lan­guages have full flexibility
  • Adding the |raw fil­ter to trans­la­tions con­tain­ing HTML pre­vents escap­ing but intro­duces cross-site script­ing risks if any para­me­ters con­tain user-pro­vid­ed data
  • Mix­ing HTML and trans­la­tions is unavoid­able in some cas­es but makes life hard­er for exter­nal trans­la­tors who must work with the syntax
  • When in doubt about whether some­thing should be a trans­la­tion or CMS con­tent, con­sid­er who needs to edit it and whether it requires dynam­ic formatting
Craft Version
Craft 5
Instructor
Level
Intermediate
Date Published
March 11, 2026