Skip to content

Converter

Bidirectional template conversion between NLT and Jinja2 syntax. All functions are in pyrx_nlt.converter.

python
from pyrx_nlt.converter import (
convert_jinja2_to_nlt,
convert_nlt_to_jinja2,
detect_template_language,
count_expressions,
ConversionResult,
)

convert_jinja2_to_nlt()

python
def convert_jinja2_to_nlt(template: str) -> tuple[str, ConversionResult]

Convert a Jinja2 template to NLT syntax. Handles UserAttribute['...'], EventAttribute['...'], control flow ({% if %}, {% for %}), and filters.

Also recovers any NLT expressions that were previously preserved in Jinja2 comments ({# NLT: {...} #}`) during a prior NLT-to-Jinja2 conversion.

Parameters

ParameterTypeDescription
templatestrThe Jinja2 template to convert.

Returns

tuple[str, ConversionResult] -- the converted template string and conversion metadata.

Example

python
template = "Hi {{ UserAttribute['First Name']|default('Customer') }}"
nlt, result = convert_jinja2_to_nlt(template)
 
print(nlt)
# 'Hi `{the user\'s First Name, or "Customer"}`'
 
print(result.count)
# 1
 
print(result.source_language)
# "jinja2"
 
print(result.target_language)
# "nlt"

Supported Conversions

Variables:

  • {{ UserAttribute['Field'] }} with all modifier variants (default, upper, lower, title, truncate, round, length, first, last, sort, join, replace)
  • {{ EventAttribute['event.Field'] }} with default and required variants
  • MOE_NOT_SEND defaults are converted to the required modifier

Control flow:

  • {% if UserAttribute['X'] == 'Y' %} / {% elif %} / {% else %} / {% endif %}
  • {% if EventAttribute['X.Y'] == 'Z' %}
  • {% if UserAttribute['X'] is defined %} (existence check)
  • {% for item in UserAttribute['X'] %} / {% endfor %}
  • {% set x = expr %}
  • {% raw %}...{% endraw %}

convert_nlt_to_jinja2()

python
def convert_nlt_to_jinja2(template: str) -> tuple[str, ConversionResult]

Convert an NLT template to Jinja2 syntax.

NLT-only constructs ({sum}, {average}, {count}, {list}, {table}) have no Jinja2 equivalent. They are preserved in Jinja2 comments as {# NLT: {original} #}` so round-trip conversions can recover them.

Parameters

ParameterTypeDescription
templatestrThe NLT template to convert.

Returns

tuple[str, ConversionResult] -- the converted template string and conversion metadata. The warnings field will contain messages about any NLT-only constructs that were preserved as comments.

Example

python
template = '`{the user\'s First Name, or "Customer"}`'
j2, result = convert_nlt_to_jinja2(template)
 
print(j2)
# "{{ UserAttribute['First Name']|default('Customer') }}"
 
print(result.count)
# 1
 
print(result.warnings)
# []
python
# NLT-only construct
template = "`{sum of the user's Order Amounts}`"
j2, result = convert_nlt_to_jinja2(template)
 
print(j2)
# "`{# NLT: `{sum of the user's Order Amounts}` #}"
 
print(result.warnings)
# ["NLT-only expression preserved as comment: `{sum of the user's Order Amounts}`"]

Supported Conversions

Variables:

  • {the user's Field} with all modifier variants (required, or, uppercase, lowercase, titlecase, truncate, round, length, first, last, sort, join, replace)
  • {the Field from the trigger event} with modifier variants
  • {the Field from the EventName event} with modifier variants

Control flow:

  • {if the user's X is "Y"} / {else if} / {else} / {end if}
  • {if the user's X is set}
  • {for item in the user's X} / {end for}
  • {set x to expr}
  • {item.property} / {loop.index}

NLT-only (preserved as comments):

  • {sum of ...}, {average of ...}, {count of ...}
  • {list ...}, {table ...}

detect_template_language()

python
def detect_template_language(
template: str,
) -> Literal["nlt", "jinja2", "mixed", "none"]

Detect whether a template uses NLT syntax, Jinja2 syntax, both, or neither.

Parameters

ParameterTypeDescription
templatestrThe template to analyze.

Returns

Return ValueMeaning
"nlt"Template contains only NLT expressions.
"jinja2"Template contains only Jinja2 expressions ({{ }} or {% %}).
"mixed"Template contains both NLT and Jinja2 expressions.
"none"Template contains no dynamic expressions (plain HTML/text).

Example

python
detect_template_language("`{the user's Name}`")
# "nlt"
 
detect_template_language("{{ UserAttribute['Name'] }}")
# "jinja2"
 
detect_template_language("`{the user's Name}` {{ foo }}")
# "mixed"
 
detect_template_language("<p>Hello world</p>")
# "none"
Tip

Use this function in migration pipelines to skip templates that are already in the target format and flag "mixed" templates for manual review.


count_expressions()

python
def count_expressions(template: str) -> tuple[int, int]

Count NLT and Jinja2 expressions in a template.

Parameters

ParameterTypeDescription
templatestrThe template to analyze.

Returns

tuple[int, int] -- (nlt_count, jinja2_count).

Example

python
nlt_count, j2_count = count_expressions(
'`{the user\'s Name}` {{ UserAttribute["Email"] }}'
)
# nlt_count: 1, j2_count: 1

ConversionResult

python
@dataclass
class ConversionResult:
count: int = 0
warnings: list[str] = field(default_factory=list)
unhandled: list[str] = field(default_factory=list)
source_language: Literal["nlt", "jinja2", "mixed", "none"] = "none"
target_language: Literal["nlt", "jinja2"] = "nlt"

Metadata returned alongside every conversion.

FieldTypeDescription
countintNumber of expressions successfully converted.
warningslist[str]Conversion warnings, e.g. NLT-only constructs preserved as comments.
unhandledlist[str]Expressions that could not be converted and were left unchanged.
source_languageLiteral["nlt", "jinja2", "mixed", "none"]The detected language of the input template.
target_languageLiteral["nlt", "jinja2"]The language the template was converted to.