Use the Smartcat template engine

Overview

Using Smartcat Template Engine technology, you can create your own templates that Smartcat uses to generate documentation. For example, you can create unique templates of invoices and quotes for a specific client.


How it works

Templates are formed according to special markup elements and a data model that you set in Smartcat for the corresponding type of document.

A data model is a set of fields containing information about model elements. For example, consider a model that Smartcat uses to generate documents for work done. The model has the following fields:

Field name Description
Name The project name
Price The cost of work
Words Translated words
Date Due date
Executive.FirstName A linguist's name
Executive.LastName A linguist's surname
Executive.Price A linguist's rate

A template contains text and tags, which are used to display model elements. To get output from a model, use the syntax <<[Field1]>>, where Field1 is the name of an element.

The following example shows information about a particular job:

Template Output
Project: <<[Name]>>
Deadline: <<[Date]>>
Assignee: <<[Executive.FirstName + " " + Executive.LastName]>>
Rate: <<[Executive.Price * Words]>> Project: PRESS_RELEASE_APR2020
Deadline: 02.04.2020
Assignee: Oliver Cross
Rate: 0.44

Smartcat Template Engine lets you perform arithmetic operations such as addition (+), subtraction (-), multiplication (*), and division (/) within a template. You can use each operation for numeric values such as rates and words. Fields that contain string values can be operated on too, in a different way. For example, FirstName and LastName form the full name in the output by using the plus sign.


Advanced features

Loops

The template engine also lets you use loops, which is especially useful for forming an extensive list of data. The loop feature has the following form:

<<foreach [item in Items]>>
<<[item]>>
<</foreach>>

Where Items is an array, item is a single element of an array, and [item] prints out an element.

Loop examples

Suppose the array Items contains the string values item1, item2, and item3. The output of the template looks like the table below.

Template Output
<<foreach [item in items]>>

<<[item]>>

<</foreach>> | item1
item2
item3 |

To display the elements as a numbered list:

Template Output
1. <<foreach [item in items]>><<[item]>>

<</foreach>> | 1. item1
2. item2
3. item3 |

How loops help to output data

Suppose you have the data model Contracts with a list of contracts. Each contract contains information about the price, client, and manager. The fields for the model are:

Name Description
Clients.Name A client's company name
Price The quote for a job
Managers.Name A manager's name

The template for the model is:

Client Manager Price
<<foreach [ c in Contracts ]>><<[c.Clients.Name]>> <<[c.Managers.Name]>> <<[c.Price]>><</foreach>>
Total: <<[Contracts.Sum(c => c.Price)]>>

Possible output:

Client Manager Price
A Company John Smith 1200000
B Ltd. John Smith 750000
C & D John Smith 350000
E Corp. Tony Anderson 650000
F & Partners Tony Anderson 550000
G & Co. July James 350000
H Group July James 250000
I & Sons July James 100000
J Ent. July James 100000
Total: 4300000

Now change the data model slightly, so you have a list of managers where each one leads a list of contracts, and each contract relates to a client.

Template:

Manager/Client Price
<<foreach [ m in Managers ]>><<[m.Name]>> <<[m.Contracts.Sum(c => c.Price)]>>
<<foreach [ c in m.Contracts ]>> <<[c.Clients.Name]>> <<[c.Price]>><</foreach>><</foreach>>
Total: <<[Contracts.Sum(c => c.Price)]>>

Output:

Manager/Client Price
John Smith 2300000
A Company 1200000
B Ltd. 750000
C & D 350000
Tony Anderson 1200000
E Corp. 650000
F & Partners 550000
July James 800000
G & Co. 350000
H Group 250000
I & Sons 100000
J Ent. 100000
Total: 4300000

Now form the client list for each manager.

Template:

Manager Clients
<<foreach [ m in Managers ]>><<[m.Name]>> <<foreach [ c in m.Contracts ]>><<[c.Clients.Name]>>

<</foreach>><</foreach>> |

Output:

Manager Clients
John Smith A Company
B Ltd.
C & D
Tony Anderson E Corp.
F & Partners
July James G & Co.
H Group
I & Sons
J Ent.

You can set the manager column by using -greedy.

Template:

Managers
<<foreach [m in ds.Managers]>><<[m.Name]>><</foreach -greedy>>

Output:

Managers
John Smith
Tony Anderson
July James

Conditional operators

If you want the output to match specific conditions, use conditional operators.

<<if [conditional_expression1]>>
template_option1
<<elseif [conditional_expression2]>>
template_option2
...
<<else>>
default_template_option
<</if>>

Conditional_expression is a condition check that returns either true or false.

Suppose you have the data model Items with the following strings: item1, item2, and item3.

The template below checks whether the elements of the array ([!items.Any()]) exist. If they do, the template displays the number of elements; otherwise, a no items message appears.

Template Output
You have chosen <<if [!items.Any()]>>no items<<else>><<[items.Count()]>> item(s)<</if>>. You have chosen 3 item(s).

The function IndexOf() marks even elements with yellow color:

Template Output
<<foreach [item in items]>><<if [IndexOf() % 2 == 0]>><<[item]>>

<<else>><<[item]>>

<</if>><</foreach>> | item1
item2
item3 |

Here you output elements of an array, or No data in case no element exists.

<<if [!items.Any()]>>No data.
<<else>><<foreach [item in items]>><<[item]>>
<</foreach>><</if>>

Tables and conditional operators

Using conditional operators, you can display data or apply styles to rows of a table depending on conditions. The rows in the table below are colored according to a specific conditional expression.

Column 1 Column 2 Column 3
<<if ...>> ... ... ...
<<elseif ...>> ... ... ...
<<else>> ... ... ... <</if>>

To showcase how it works, use the model Client with the following fields:

Name Description
Name self-explanatory
Country self-explanatory
LocalAddress self-explanatory

The template below outputs data related to all clients. New Zealand clients are marked with green color, and columns for such clients are merged and contain only LocalAddress values.

Column 1 Column 2 Column 3
<<foreach [in clients]>><<if [Country == "New Zealand"]>><<[Name]>> <<[LocalAddress]>>
<<else>><<[Name]>> <<[Country]>> <<[LocalAddress]>>

Output:

Client Country Local Address
A Company Australia 219-241 Cleveland St STRAWBERRY HILLS NSW 1427
B Ltd. Brazil Avenida João Jorge, 112, ap. 31, Vila Industrial, Campinas — SP, 13035-680
C & D Canada 101-3485 RUE DE LA MONTAGNE, MONTRÉAL (QUÉBEC) H3G 2A6
E Corp. 445 Mount Eden Road, Mount Eden, Auckland 1024
F & Partners 20 Greens Road, Tuahiwi, Kaiapoi 7691
G & Co. Greece Karkisias 6, GR-111 42 ATHINA, GRÉCE
H Group Hungary Budapest, Fiktív utca 82., IV. em./28., 2806
I & Sons 43 Vogel Street, Roslyn, Palmerston North 4414

This template displays the No data message if no data is found.

Client Country Local Address
<<if [!clients.Any()]>>No data
<<else>><<foreach [in clients]>><<[Name]>> <<[Country]>> <<[LocalAddress]>><</foreach>><</if>>

Output:

Client Country Local Address
No data

You can also remove content conditionally:

Template Output
Header
<<if [false]>>Content to remove<</if>>
Footer Header
Footer

Here you use -greedy:

Template Output
Header
<<if [false]>>Content to remove<</if -greedy>>
Footer Header
Footer

Auxiliary methods for arrays

Smartcat Template Engine also lets you work flexibly with arrays by applying auxiliary methods.

Suppose you have a data model containing the field persons, that is, the list of employees.

The description of the data model Person:

Name
Name
Age
Subordinates
Salary

This template displays the names of employees older than 50 years:

Template Output
<<foreach [person in persons.All(p => p.Age > 50)]>>

<<[person.Name]>>

<</foreach>> | Joe Black
Ivan Lock
Jane Wood |

Now get a total of employees' salaries:

Template Output
<<[persons.Sum( p => p.Salary)]>> 490000

The table below describes all available methods, with examples drawn from two arrays, persons and otherPersons. Both hold information about the company's employees.

Method Template
All(Predicate) persons.All(p => p.Age < 50)
Any() persons.Any()
Average(Selector) persons.Average(p => p.Age)
Concat(IEnumerable) persons.Concat(otherPersons)
Contains(Object) persons.Contains(otherPersons.First())
Count() persons.Count()
Count(Predicate) persons.Count(p => p.Age > 30)
Distinct() persons.Distinct()
First() persons.First()
First(Predicate) persons.First(p => p.Age > 30)
FirstOrDefault() persons.FirstOrDefault()
FirstOrDefault(Predicate) persons.FirstOrDefault(p => p.Age > 30)
GroupBy(Selector) persons.GroupBy(p => p.Age)
Last() persons.Last()
Last(Predicate) persons.Last(p => p.Age > 100)
LastOrDefault() persons.LastOrDefault()
LastOrDefault(Predicate) persons.LastOrDefault(p => p.Age > 100)
Max(ComparableSelector) persons.Max(p => p.Age)
Min(ComparableSelector) persons.Min(p => p.Age)
OrderBy(ComparableSelector) persons.OrderBy(p => p.Age)
OrderByDescending(ComparableSelector) persons.OrderByDescending(p => p.Age)
Single() persons.Single()
Single(Predicate) persons.Single(p => p.Name == "John Smith")
SingleOrDefault() persons.SingleOrDefault()
SingleOrDefault(Predicate) persons.SingleOrDefault(p => p.Name == "John Smith")
Skip(int) persons.Skip(10)
SkipWhile(Predicate) persons.SkipWhile(p => p.Age < 21)
Sum(Selector) persons.Sum(p => p.Children.Count())
Take(int) persons.Take(5)
TakeWhile(Predicate) persons.TakeWhile(p => p.Age < 50)
Union(IEnumerable) persons.Union(otherPersons)
Where(Predicate) persons.Where(p => p.Age > 18)

The OrderBy and OrderByDescending methods also support chaining with ThenBy and ThenByDescending, for example persons.OrderBy(p => p.Age).ThenByDescending(p => p.Name).ThenBy(p => p.Children.Count()).


Appendix for developers

Smartcat Template Engine uses a subset of C# syntax (C# Language Specification 5.0) in templates. For all primitive data types, such as strings, you can use BCL methods. The methods mentioned in the Auxiliary methods for arrays section are taken from LINQ.

Still need help?

Our support team responds within one business day.

Open a support case