Skip to content


A template text is essentially a placeholder text parsed by the Grammar Engine. While processing, detected placeholders will be filled with variables (as far as they're defined).

The values inserted are typically adjusted to be grammatically correct given their context. For this to work properly, it might be necessary to add extra markup, denoting additional information such as required articles or grammatical cases.

Variable Types

The Grammer Engine differentiates between three types of variables that may be inserted using placeholders.

Built-in Constants

Built-in Constants have fixed values and start with grammar::. They can't be overwritten in any way. The following table includes a list of all constants and example values.

Constant Description Example Value
grammar::company The company this library is licensed to. Sample Corp.
grammar::language The current language's language code. de
grammar::languages A list of the supported languages. en,de,fr
grammar::project The project this library is licensed for. Evaluation
grammar::validity The date up till which this evaluation copy works. 01-Jan-2023
grammar::verdate The date this version has been prepared. 17-May-2022 16:49:56
grammar::version Internal version number of this library. 1.7.1
grammar::githash Internal Git revision hash identifying your build. 9fd11ec0848b719980b153e8d8e1467228468f2e

These may be used just like any other variable, although they're mostly for debugging purposes, e.g. to determine how old a specific build is or which fixes are included.

Powered by Lingoona Grammar Engine v<<grammar::version>>

This example would result in the version number to be inserted:

Powered by Lingoona Grammar Engine v1.7.1

Global Variables

Global Variables are identified by name and can be set by developers. These can be used like any other variable, for example:

Welcome, <<player_name>>. I've been waiting for you. My name is <<npc>>. Is this your first time <<l:location>>?

Based on the values of these variables, the results could look like this:

Welcome, Mr. Jones. I've been waiting for you. My name is Müller. Is this your first time in Berlin?

It's completely up to the developers which variables are available and their actual content.

Dynamic Variables

Dynamic Variables are identified by numbers and are passed directly when the Grammar Engine is invoked.

Dynamic variables are always identified by an increasing index, starting at 1, then 2, etc. A special variable 0 exists, but is used for internal purposes only and shouldn't be queried as it's exact contents may expose undefined behavior.

Basic Text Template

A minimalistic template is just a static text with no special placeholders:

Hello World!

This will be returned as-is without modifications.

Placeholders can be defined using special opening and closing brackets. While these might be project dependent, the default format is <<var>>, where var might be a named constant or variable or a number denoting a dynamic parameter.

Hello, <<name>>! Have you seen the <<object>>?

The final result could look like this:

Hello, Michael! Have you seen the tower?

Implicit Context Detection

If no tagging information is provided inside the placeholder, the Grammar Engine will try to implicitly derive the needed articles or pronouns together with the applicable grammatical case based on the word in front of the placeholder.

While this might be of limited use in languages such as Russian or even English, it allows most German and French use cases to simply skip tagging altogether.

<<X:1>> - You see a <<1>>.

This example will print the raw variable contents (enforced by the tagging with X:) followed by the completed sentence. Here the English parser will detect the indetermined article a in front of the placeholder and set the proper internal request flag accordingly.

skeleton^n - You see a skeleton.

axe^n - You see an axe.

golden sword^nd - You see the golden sword.

Mario^M - You see Mario.

As you can see, the article is dynamically adjusted based on the variable contents. The following line would net the same results, explicitly tagging the placeholder to show an:

<<X:1>> - You see <<a:1>>.

For this to work properly, the used articles have to assume the placeholder is going to hold an male singular name, even if that won't be the case:

🇩🇪<<X:1>> - Ich bringe meinen <<1>> ins Haus.

Here the German meinen will be properly detected as the accusative version of the first person singular possessive pronoun. This will result in the proper possessive pronoun being used, even if the variable later holds a female or neuter name.

🇩🇪Hund^m - Ich bringe meinen Hund ins Haus.

🇩🇪Ente^f - Ich bringe meine Ente ins Haus.

🇩🇪Gäste^p - Ich bringe meine Gäste ins Haus.

Explicit Context Definition

Instead of relying on automatic context detection – or whenever this isn't possible – there's also a way to define a grammatical case and/or specify extra flags when defining placeholders.

Default Case Tags Case & Tags
<<var>> <<case:var>> <<tags:var>> <<case,tags:var>>

Secondary Variable

Some tags might require a secondary variable placed after a comma, like <<case,tags:var1,var2>>.

Grammatical Case

The Grammar Library is capable of handling the following grammatical cases. If no case is given, the nominative case is assumed.

Case Tag Description
nom Nominative
gen Genitive
dat Dative
acc Accusative
ins Instrumental (Russian/Polish)
pre Prepositional (Russian)
loc Locative (Polish)
voc Vocative (Polish)

Native Cases

The Russian version also accepts the case names in Cyrillic (име, род, дат, вин, тво, and пре), while the German version accepts akk for Akkusative.

Placeholder Tags

Placeholder tags may be a combination of the following tags. Certain combinations might cause undefined behavior. For example, you shouldn't use combinations such as Zz, transforming all characters to uppercase and lowercase at the "same" time.

General Tags

Tag Description
x Don't insert the variable itself.
X Insert the variable 1:1 (disables processing).
a Add indefinite article.
A Add definite article.
c Insert first character lowercase.
C Insert first character uppercase.
z Insert all characters lowercase.
Z Insert all characters uppercase.
t Use Regular Title Case.
T Force Full Title Case for all words.
g Insert genitive with an indefinite article. Requires two variables.
gu ≥1.7.1Insert short genitive, if possible (always treat owner as a proper name). Requires two variables.
G Insert genitive with a definite article. Requires two variables.
i Assume variable is a number and create an ordinal number (eg. 1st or 3rd)
I Same as i, but use declension for the gender of a second variable.
l Insert as a current location, e.g. in ….
L Insert as a destination, e.g. to ….
q Add single quotes, if this is a proper name.
Q Add double quotes, if this is a proper name.
R Assume variable is a number and use Roman literals.
m Insert the plural form. If there's a number preceding the placeholder, it determines singular or plural form.
n Assume the variable is a number and use a written word, if available. Most languages this is limited to 1 to 12.
f# ≥1.6.3Properly format the passed English formatted number accordingly. The optional number # defines the number of decimal places (forces rounding).
F# ≥1.6.3Properly format the passed English formatted number while forcing thousands separators (if applicable). The optional number # defines the number of decimal places (forces rounding).

Pronoun Tags

Tag Description
d  Insert demonstrative pronoun with variable's value.
D  Insert demonstrative pronoun without variable's value to be used in a substitutional way (e.g. the English this or whose).
o#  Insert possessive pronoun for #th person (1-3), third person requires a second variable for the gender.
O#  Insert possessive pronoun substitutional for #th person (1-3), third person requires a second variable for the gender.
p#  Insert personal pronoun for #th person (1-3), third person requires a second variable for the gender.
P#  Insert dative personal pronoun for #th person (1-3), third person requires a second variable for the gender.
r#  Insert reflexive pronoun for #th person (1-3), third person requires a second variable for the gender.


Parts of a template can be dynamically adjusted based on a variable's gender or numerical value. To achieve this, the switches "body" section is simply appended to the variable's name or index.

Gender Switches

A gender switch consists of at least a male and female case. Depending on the individual language, there can be extra cases for neuter, plural, and plural 2.


Omitted Cases

If you don't provide cases for all possibilities based on your language, the library will default the missing cases to one of the provided ones.

If required, individual cases may insert the value of the variable by using $s:

<<var{male $s/female $s/neuter $s/plural $s/plural2 $s}>>

Numerical Switches

Similar to gender switches, variables can also be evaluated to a numerical value. By default, the Grammar Engine will try to read a number from the beginning of the variable's contents.



Non-numerical Values

If there's no numerical value, a hypothetical number is determined based on the variable's value:

Value Assumed Number
<Empty> 0
No plural 1
Plural 2

If required, individual cases may insert the read number of the variable by using $d and the full value of the variable using $s.

<<var[zero $s/one $s/many $s]>>

<<var[zero $d/one $d/many $d]>>


It is possible to make a placeholder automatically show a count and adjusting to singular or plural forms accordingly.

While most of this is also possible using numerical switches, this approach allows more dynamic text as well as the use of proper plural forms.

This feature doesn't work with constants or named variables.

You can't provide constants or named variables here. This feature might be added at a later date.

Default Usage

For this to work, two placeholder indexes have to be concatenated using *:

<<X:1>> - <<X:2>> - You've obtained a <<1*2>>!

Based on the numerical value in variable 1 and the name in variable 2, this could lead to different results:

0 - item^n - You've obtained no item!

1 - item^n - You've obtained an item!

2 - item^n - You've obtained 2 items!

Forced Numbers

It's also possible to name the first index with a leading zero:

<<X:1>> - <<X:2>> - You've obtained a <<01*2>>!

This will force written out numbers in all cases:

0 - item^n - You've obtained 0 items!

1 - item^n - You've obtained 1 item!

2 - item^n - You've obtained 2 items!

Static Text

Rather than providing a second variable, it's also possible to embed text with tags directly. This is mostly useful for instances where a number is inserted into static text, but the text should change.

<<X:1>> - You've obtained a <<1*item^n>>!

0 - You've obtained no item!

1 - You've obtained an item!

2 - You've obtained 2 items!

Same results may be achieved using numerical switches.

List Formatting

The Grammar Engine is capable of automatically collecting all non-empty variables in a given range (start and end index) and formatting them into a language specific list and applying proper conjunctions and punctuation. This makes it easier to create flexible lists without having to worry about the actual amount of elements being used.

Lists may be composed utilizing <<and()>>, <<or()>>, or <<nor()>>.

Find <<and(1,4)>> inside the cave.

Assuming the dynamic variables/parameters from 1 to 4 include three names (and one empty value) this results in:

Find Mike, Jane, and Michelle inside the cave.

If only two of them are set the result is adjusted accordingly:

Find Mike and Jane inside the cave.

Last update: January 24, 2023