Linguistic Template Features¶
This guide covers VIBE's powerful linguistic features, which go beyond simple variable replacement. These tools help you correctly handle plurals, possessives, complex list formatting, and number-to-word conversions. It assumes you are familiar with the basics from the Jinja Essentials guide.
Supported Languages: English (en), Swedish (sv), German (de), French (fr), Spanish (es)
Locale-Specific Aliases: Each language provides native-language aliases for filters and tags, making templates more readable when written in that language. See the Locale-Specific Aliases section at the end of this guide.
Core Concept: The Linguistic Object¶
Behind the scenes, these filters work by passing a special Linguistic object between them. When you apply the first filter in a chain (like | plural), VIBE converts your string into this object. Subsequent filters then modify the object's properties (like its number or definiteness) before it's finally converted back to a string for printing.
This allows for powerful, context-aware transformations, such as | plural | definite correctly applying the plural definite form.
Basic Linguistic Filters¶
These filters can be applied to any string variable or literal.
| plural¶
Converts a word to its plural form based on the current language.
Arguments:
"overrides"(optional, first positional): Override irregular forms using"singular->plural"syntax. Multiple overrides can be comma-separated.if_=variable(optional): Prevents pluralization ifvariablehas a value of1.

{# English #}
You have {{ num_items }} {{ "renewal period" | plural(if_=num_items) }}.
{# num_items=1: "You have 1 renewal period." #}
{# num_items=2: "You have 2 renewal periods." #}
{# Swedish (alias: plural) #}
Det finns {{ antal }} {{ "avtal" | plural(if_=antal) }}.
{# antal=1: "Det finns 1 avtal." #}
{# antal=2: "Det finns 2 avtal." #}
{# German (alias: plural) #}
Es gibt {{ anzahl }} {{ "Vertrag" | plural(if_=anzahl) }}.
{# anzahl=1: "Es gibt 1 Vertrag." #}
{# anzahl=2: "Es gibt 2 Verträge." #}
{# French (alias: pluriel) #}
Il y a {{ nombre }} {{ "contrat" | pluriel(if_=nombre) }}.
{# nombre=1: "Il y a 1 contrat." #}
{# nombre=2: "Il y a 2 contrats." #}
{# Spanish (alias: plural) #}
Hay {{ cantidad }} {{ "contrato" | plural(if_=cantidad) }}.
{# cantidad=1: "Hay 1 contrato." #}
{# cantidad=2: "Hay 2 contratos." #}
Overriding Irregular Plurals¶
When a word has an irregular plural form not in the built-in lexicon, you can provide an override:
{# Swedish - override for uncommon words #}
{{ "gås" | plural("gås->gäss") }}
{# Output: "gäss" #}
{# Multiple overrides #}
{{ djur | plural("gås->gäss,åsna->åsnor") }}
{# English - override for domain-specific terms #}
{{ "vertex" | plural("vertex->vertices") }}
{# Output: "vertices" (also in built-in lexicon) #}
{# German #}
{{ "Virus" | plural("Virus->Viren") }}
{# Output: "Viren" #}
{# French #}
{{ "festival" | plural("festival->festivals") }}
{# Output: "festivals" (exception to -al -> -aux rule) #}
{# Spanish #}
{{ "curriculum" | plural("curriculum->curricula") }}
{# Output: "curricula" #}
The override takes precedence over both built-in irregular forms and heuristic rules.
| definite¶
Converts a word or phrase to its definite form. In English, this adds "the". In Swedish, it adds a suffix. In German/French/Spanish, it adds the appropriate article.
Arguments:
"overrides"(optional, first positional): Override irregular forms using"word->definite_form"syntax. Primarily useful for Swedish where definiteness is a suffix.
{# English #}
The subject of the agreement is {{ item | definite }}.
{# item="opportunity" -> "the opportunity" #}
{# Swedish (alias: bestamd) #}
Avtalet avser {{ item | bestamd }}.
{# item="verksamhet" -> "verksamheten" #}
{# item="avtal" -> "avtalet" #}
{# Swedish - override for uncommon words #}
{{ "test" | bestamd("test->testet") }}
{# Output: "testet" #}
{# German (alias: bestimmt) #}
Der Gegenstand ist {{ item | bestimmt }}.
{# item="Vertrag" -> "der Vertrag" #}
{# item="Vereinbarung" -> "die Vereinbarung" #}
{# French (alias: defini) #}
L'objet est {{ item | defini }}.
{# item="contrat" -> "le contrat" #}
{# item="partie" -> "la partie" #}
{# item="accord" -> "l'accord" #}
{# Spanish (alias: definido) #}
El objeto es {{ item | definido }}.
{# item="contrato" -> "el contrato" #}
{# item="parte" -> "la parte" #}
Note: Overrides are most useful for Swedish, where definiteness is expressed as a suffix with complex rules. For German, French, and Spanish, the definite article is determined by grammatical gender, which is looked up in the noun lexicon or guessed from word endings.
| possessive¶
Converts a word or phrase to its possessive/genitive form.
possessive(subject="..."): A special argument that can rephrase the entire expression.
{# English #}
This marks {{ "the contract" | possessive(subject="end") }}.
{# Output: "the end of the contract" #}
{{ "Company" | possessive }}
{# Output: "Company's" #}
{# Swedish (alias: genitiv) #}
{{ "Bolaget" | genitiv(subject="åtaganden") }}
{# Output: "Bolagets åtaganden" #}
{{ "Förlängningsperiod" | bestamd | genitiv }}
{# Output: "Förlängningsperiodens" #}
{# German (alias: genitiv) #}
{{ "Vertrag" | genitiv }}
{# Output: "des Vertrags" #}
{{ "Vereinbarung" | genitiv }}
{# Output: "der Vereinbarung" #}
{# French (alias: possessif) #}
{{ "contrat" | possessif }}
{# Output: "du contrat" #}
{{ "accord" | possessif }}
{# Output: "de l'accord" #}
{# Spanish (alias: posesivo) #}
{{ "contrato" | posesivo }}
{# Output: "del contrato" #}
{{ "parte" | posesivo }}
{# Output: "de la parte" #}
| indefinite¶
Adds an indefinite article to a word. In English, this correctly handles "a" vs "an" based on pronunciation.
{# English #}
This is {{ "agreement" | indefinite }}.
{# Output: "an agreement" #}
This is {{ "contract" | indefinite }}.
{# Output: "a contract" #}
This is {{ "university" | indefinite }}.
{# Output: "a university" (sounds like "yoo") #}
This is {{ "hour" | indefinite }}.
{# Output: "an hour" (silent h) #}
{# Swedish (alias: obestamd) #}
Detta är {{ "avtal" | obestamd }}.
{# Output: "ett avtal" (neuter) #}
Detta är {{ "kund" | obestamd }}.
{# Output: "en kund" (common) #}
{# German (alias: unbestimmt) #}
Das ist {{ "Vertrag" | unbestimmt }}.
{# Output: "ein Vertrag" (masculine) #}
Das ist {{ "Vereinbarung" | unbestimmt }}.
{# Output: "eine Vereinbarung" (feminine) #}
Das ist {{ "Dokument" | unbestimmt }}.
{# Output: "ein Dokument" (neuter) #}
{# French (alias: indefini) #}
C'est {{ "contrat" | indefini }}.
{# Output: "un contrat" (masculine) #}
C'est {{ "partie" | indefini }}.
{# Output: "une partie" (feminine) #}
{# Spanish (alias: indefinido) #}
Es {{ "contrato" | indefinido }}.
{# Output: "un contrato" (masculine) #}
Es {{ "parte" | indefinido }}.
{# Output: "una parte" (feminine) #}
| itemize¶
Handles phrases with multiple items, like "goods and services". It controls the conjunction word used when the phrase is finally printed.
{# English #}
{{ "goods, support and services" | definite | itemize(conjunction="or") }}
{# Output: "the goods, the support, or the services" #}
{# Swedish (alias: upprakning) #}
{{ "varor, stöd och tjänster" | bestamd | upprakning(konjunktion="eller") }}
{# Output: "varorna, stödet eller tjänsterna" #}
{# German (alias: auflistung) #}
{{ "Waren, Support und Dienstleistungen" | bestimmt | auflistung(konjunktion="oder") }}
{# Output: "die Waren, der Support oder die Dienstleistungen" #}
{# French (alias: enumerer) #}
{{ "biens, support et services" | defini | enumerer(conjonction="ou") }}
{# Output: "les biens, le support ou les services" #}
{# Spanish (alias: enumerar) #}
{{ "bienes, soporte y servicios" | definido | enumerar(conjuncion="o") }}
{# Output: "los bienes, el soporte o los servicios" #}
Company Name Utilities¶
| strip_company_form¶
Strips legal company form designations from a company name, converting a formal name like "Inka Interactive Ekonomisk förening" to the colloquial "Inka Interactive".
Currently supported: Swedish (sv) only. For all other locales, the filter is a no-op and returns the input unchanged.
Swedish alias: utan_bolagsform
The filter handles both suffix and prefix positions with word-boundary awareness, so names like "ABB" or "IKEA" are not mangled.
{# Swedish — suffix forms (most common) #}
{{ sokande_namn | strip_company_form }}
{# "Inka Interactive Ekonomisk förening" → "Inka Interactive" #}
{# "Volvo AB" → "Volvo" #}
{# "Sjöutsikten Brf" → "Sjöutsikten" #}
{# Swedish — prefix forms #}
{{ "AB Volvo" | strip_company_form }}
{# Output: "Volvo" #}
{# Swedish alias #}
{{ sokande_namn | utan_bolagsform }}
{# "Bygg & Montage HB" → "Bygg & Montage" #}
{# English — no-op #}
{{ "Volvo AB" | strip_company_form }}
{# Output: "Volvo AB" (unchanged) #}
Recognized Swedish company forms:
| Full form | Abbreviation(s) |
|---|---|
| Aktiebolag | AB |
| Kommanditbolag | KB |
| Handelsbolag | HB |
| Ekonomisk förening | Ek. för., Ek.för. |
| Bostadsrättsförening | Brf, Brf. |
| Ideell förening | Id. för., Id.för. |
| Enskild firma | EF |
| Stiftelse | — |
| Samfällighetsförening | — |
| Kooperativ hyresrättsförening | — |
Note: The filter is case-insensitive ("volvo ab" → "volvo", "Volvo AB" → "Volvo"). If no company form is found, the input is returned unchanged.
Number-to-Word Conversion Filters¶
For legal and formal documents, it's often necessary to write out numbers as words. These filters handle the conversion automatically based on the current locale.
| cardinal¶
Converts a number into its cardinal word form (e.g., one, two, three).
cardinal(cutoff=number): An optional argument. If the input number is greater than the cutoff, the filter will return the number as digits instead of words.
{# English #}
The term is {{ years | cardinal }} years.
{# years=3: "The term is three years." #}
{{ amount | cardinal(cutoff=100) }} dollars
{# amount=95: "ninety-five dollars" #}
{# amount=101: "101 dollars" #}
{# Swedish (alias: kardinal) #}
Avtalet gäller i {{ ar | kardinal }} år.
{# ar=3: "Avtalet gäller i tre år." #}
{# ar=21: "Avtalet gäller i tjugoett år." #}
{# German (alias: kardinal) #}
Der Vertrag gilt für {{ jahre | kardinal }} Jahre.
{# jahre=3: "Der Vertrag gilt für drei Jahre." #}
{# jahre=21: "Der Vertrag gilt für einundzwanzig Jahre." #}
{# French (alias: cardinal) #}
Le contrat dure {{ annees | cardinal }} ans.
{# annees=3: "Le contrat dure trois ans." #}
{# annees=80: "Le contrat dure quatre-vingts ans." #}
{# Spanish (alias: cardinal) #}
El contrato dura {{ anos | cardinal }} años.
{# anos=3: "El contrato dura tres años." #}
{# anos=21: "El contrato dura veintiuno años." #}
| ordinal¶
Converts a number into its ordinal word form (e.g., first, second, third).
{# English #}
This is the {{ count | ordinal }} amendment.
{# count=1: "the first amendment" #}
{# count=22: "the twenty-second amendment" #}
{# Swedish (alias: ordinal) #}
Detta är det {{ nummer | ordinal }} tillägget.
{# nummer=1: "det första tillägget" #}
{# nummer=3: "det tredje tillägget" #}
{# German (alias: ordinal) #}
Dies ist die {{ nummer | ordinal }} Änderung.
{# nummer=1: "die erste Änderung" #}
{# nummer=3: "die dritte Änderung" #}
{# French (alias: ordinal) #}
C'est le {{ numero | ordinal }} amendement.
{# numero=1: "le premier amendement" #}
{# numero=2: "le deuxième amendement" #}
{# Spanish (alias: ordinal) #}
Esta es la {{ numero | ordinal }} enmienda.
{# numero=1: "la primera enmienda" #}
{# numero=2: "la segunda enmienda" #}
| doublet¶
Creates a "doublet" format common in legal documents, showing both the word and digit form.
doublet(unit="..."): An optional argument to append a unit to the end.
{# English #}
{{ days | doublet }} days
{# days=30: "thirty (30) days" #}
{{ days | doublet(unit="business days") }}
{# days=30: "thirty (30) business days" #}
{# Swedish (alias: dublett) #}
{{ dagar | dublett }} dagar
{# dagar=30: "trettio (30) dagar" #}
{{ dagar | dublett(unit="arbetsdagar") }}
{# dagar=30: "trettio (30) arbetsdagar" #}
{# German (alias: wort_und_zahl) #}
{{ tage | wort_und_zahl }} Tage
{# tage=30: "dreißig (30) Tage" #}
{{ tage | wort_und_zahl(unit="Werktage") }}
{# tage=30: "dreißig (30) Werktage" #}
{# French (alias: doublet) #}
{{ jours | doublet }} jours
{# jours=30: "trente (30) jours" #}
{{ jours | doublet(unit="jours ouvrables") }}
{# jours=30: "trente (30) jours ouvrables" #}
{# Spanish (alias: doblete) #}
{{ dias | doblete }} días
{# dias=30: "treinta (30) días" #}
{{ dias | doblete(unit="días hábiles") }}
{# dias=30: "treinta (30) días hábiles" #}
| roman¶
Converts a number to Roman numerals. Useful for legal section numbering.
roman(case="upper")(default): Uppercase numerals (I, II, III)roman(case="lower"): Lowercase numerals (i, ii, iii)
{# All languages - Roman numerals are universal #}
{# English #}
Article {{ section | roman }}
{# section=4: "Article IV" #}
{# section=1999: "Article MCMXCIX" #}
{# Swedish (alias: romersk) #}
Avsnitt {{ avsnitt | romersk }}
{# avsnitt=4: "Avsnitt IV" #}
{{ avsnitt | romersk(case="lower") }}
{# avsnitt=4: "iv" #}
{# German (alias: romisch) #}
Abschnitt {{ abschnitt | romisch }}
{# abschnitt=4: "Abschnitt IV" #}
{# French (alias: romain) #}
Section {{ section | romain }}
{# section=4: "Section IV" #}
{# Spanish (alias: romano) #}
Sección {{ seccion | romano }}
{# seccion=4: "Sección IV" #}
Note: Values outside 1-3999 are returned unchanged.
| alpha¶
Converts a number to an alphabetical label (1=A, 2=B, ..., 26=Z). Useful for list item markers.
alpha(case="upper")(default): Uppercase letters (A, B, C)alpha(case="lower"): Lowercase letters (a, b, c)
{# All languages - alphabetical labels are universal #}
{# English #}
Exhibit {{ num | alpha }}
{# num=1: "Exhibit A" #}
{# num=26: "Exhibit Z" #}
{# Swedish (alias: alfabetisk) #}
Bilaga {{ num | alfabetisk }}
{# num=1: "Bilaga A" #}
{{ num | alfabetisk(case="lower") }}
{# num=1: "a" #}
{# German (alias: alphabetisch) #}
Anlage {{ num | alphabetisch }}
{# num=1: "Anlage A" #}
{# French (alias: alphabetique) #}
Annexe {{ num | alphabetique }}
{# num=1: "Annexe A" #}
{# Spanish (alias: alfabetico) #}
Anexo {{ num | alfabetico }}
{# num=1: "Anexo A" #}
Note: Values outside 1-26 are returned unchanged (no AA, AB, etc.).
Advanced Conditional Lists: {% enumerate %}¶
For creating a list of items where each item has its own inclusion condition, use the {% enumerate %} block tag. It automatically handles commas and conjunctions for a grammatically perfect result.
Inside the block, you define items using the {% item if ... %} tag:
Example: Paragraph Style¶

{# English #}
The limitation does not apply to {%
enumerate conjunction="or" %}{%
item if carveout['breach'] %}breach of confidentiality{% enditem %}{%
item if carveout['infringement'] %}infringement of IPR{% enditem %}{%
item if carveout['misconduct'] %}reckless conduct{% enditem %}{%
endenumerate %}.
{# All true: "breach of confidentiality, infringement of IPR, or reckless conduct." #}
{# First and last: "breach of confidentiality or reckless conduct." #}
{# First only: "breach of confidentiality." #}
{# Swedish (localized tags) #}
Ansvarsbegränsningen gäller inte {%
upprakning konjunktion="eller" %}{%
punkt om undantag['sekretess'] %}brott mot sekretess{% slut_punkt %}{%
punkt om undantag['immaterialratt'] %}intrång i immateriella rättigheter{% slut_punkt %}{%
punkt om undantag['grov_oaktsamhet'] %}grov oaktsamhet{% slut_punkt %}{%
slut_upprakning %}.
{# German (localized tags) #}
Die Haftungsbeschränkung gilt nicht für {%
auflistung konjunktion="oder" %}{%
punkt wenn ausnahme['vertraulichkeit'] %}Verletzung der Vertraulichkeit{% ende_punkt %}{%
punkt wenn ausnahme['ip'] %}Verletzung von Schutzrechten{% ende_punkt %}{%
punkt wenn ausnahme['fahrlassigkeit'] %}grobe Fahrlässigkeit{% ende_punkt %}{%
ende_auflistung %}.
{# French (localized tags) #}
La limitation ne s'applique pas à {%
enumeration conjonction="ou" %}{%
element si exception['confidentialite'] %}violation de la confidentialité{% fin_element %}{%
element si exception['pi'] %}violation de la propriété intellectuelle{% fin_element %}{%
element si exception['negligence'] %}faute lourde{% fin_element %}{%
fin_enumeration %}.
{# Spanish (localized tags) #}
La limitación no se aplica a {%
enumeracion conjuncion="o" %}{%
elemento si excepcion['confidencialidad'] %}incumplimiento de confidencialidad{% fin_elemento %}{%
elemento si excepcion['pi'] %}infracción de PI{% fin_elemento %}{%
elemento si excepcion['negligencia'] %}negligencia grave{% fin_elemento %}{%
fin_enumeracion %}.
Example: List Style¶
You can also generate a formatted <ul> list with correct end-of-line punctuation.
{# English #}
The limitation does not apply to:
{% enumerate style="list", conjunction="or" %}
{% item if breach %}Breach of confidentiality{% enditem %}
{% item if infringement %}Infringement of IPR{% enditem %}
{% endenumerate %}
{# Swedish #}
Ansvarsbegränsningen gäller inte:
{% upprakning stil="list", konjunktion="eller" %}
{% punkt om sekretessbrott %}Brott mot sekretess{% slut_punkt %}
{% punkt om immaterialrattsintrong %}Intrång i immateriella rättigheter{% slut_punkt %}
{% slut_upprakning %}
{# German #}
Die Haftungsbeschränkung gilt nicht für:
{% auflistung stil="list", konjunktion="oder" %}
{% punkt wenn vertraulichkeit %}Verletzung der Vertraulichkeit{% ende_punkt %}
{% punkt wenn schutzrechte %}Verletzung von Schutzrechten{% ende_punkt %}
{% ende_auflistung %}
{# French #}
La limitation ne s'applique pas à:
{% enumeration style="list", conjonction="ou" %}
{% element si confidentialite %}Violation de la confidentialité{% fin_element %}
{% element si propriete_intellectuelle %}Violation de la propriété intellectuelle{% fin_element %}
{% fin_enumeration %}
{# Spanish #}
La limitación no se aplica a:
{% enumeracion estilo="list", conjuncion="o" %}
{% elemento si confidencialidad %}Incumplimiento de confidencialidad{% fin_elemento %}
{% elemento si propiedad_intelectual %}Infracción de PI{% fin_elemento %}
{% fin_enumeracion %}
Possible Output (if both are true):
The limitation of liability does not apply to:
- Breach of confidentiality; or
- Infringement of IPR.
enumerate Tag Arguments¶
style(optional):"paragraph"(default): Creates an inline, comma-separated list."list": Creates a<ul>bullet point list with correct punctuation.
conjunction(optional):"and"(default): Uses the localized word for "and"."or": Uses the localized word for "or".- Any other string: Uses the provided string verbatim (e.g.,
"och/eller").
transform(optional): Applies a filter to each item before joining."possessive": Applies the possessive filter to each item."capitalize": Capitalizes the first letter of each item.
Locale-Specific Aliases¶
To make templates more readable when written in a specific language, VIBE provides native-language aliases for filters and tags. The English (canonical) names always work, but you can use the aliases when your template locale matches.
Filter Aliases by Language¶
| Filter (English) | Swedish (sv) | German (de) | French (fr) | Spanish (es) |
|---|---|---|---|---|
plural |
plural |
plural |
pluriel |
plural |
definite |
bestamd |
bestimmt |
defini |
definido |
possessive |
genitiv |
genitiv |
possessif |
posesivo |
indefinite |
obestamd |
unbestimmt |
indefini |
indefinido |
cardinal |
kardinal |
kardinal |
cardinal |
cardinal |
ordinal |
ordinal |
ordinal |
ordinal |
ordinal |
doublet |
dublett |
wort_und_zahl |
doublet |
doblete |
itemize |
upprakning |
auflistung |
enumerer |
enumerar |
roman |
romersk |
romisch |
romain |
romano |
alpha |
alfabetisk |
alphabetisch |
alphabetique |
alfabetico |
strip_company_form |
utan_bolagsform |
— | — | — |
Tag Aliases by Language¶
The enumerate tag and its sub-tags also have localized aliases:
| Tag (English) | Swedish (sv) | German (de) | French (fr) | Spanish (es) |
|---|---|---|---|---|
enumerate |
upprakning |
auflistung |
enumeration |
enumeracion |
endenumerate |
slut_upprakning |
ende_auflistung |
fin_enumeration |
fin_enumeracion |
item |
punkt |
punkt |
element |
elemento |
enditem |
slut_punkt |
ende_punkt |
fin_element |
fin_elemento |
Tag Parameter Aliases¶
Parameters inside tags can also use localized names:
| Parameter (English) | Swedish (sv) | German (de) | French (fr) | Spanish (es) |
|---|---|---|---|---|
conjunction |
konjunktion |
konjunktion |
conjonction |
conjuncion |
style |
stil |
stil |
style |
estilo |
transform |
omvandla |
umwandeln |
transformer |
transformar |
if |
om |
wenn |
si |
si |
Note: The English names always work regardless of template locale. Aliases are purely for improved readability.
Filter Chaining¶
Filters can be chained together to apply multiple transformations:
{# English #}
{{ "renewal period" | plural | definite }}
{# Output: "the renewal periods" #}
{# Swedish #}
{{ "Förlängningsperiod" | plural | bestamd | genitiv }}
{# Output: "Förlängningsperiodernas" #}
{# German #}
{{ "Vertrag" | plural | bestimmt }}
{# Output: "die Verträge" #}
{# French #}
{{ "contrat" | pluriel | defini }}
{# Output: "les contrats" #}
{# Spanish #}
{{ "contrato" | plural | definido }}
{# Output: "los contratos" #}
Defined Terms¶
The defined-terms system highlights terms from a "Definitions" section in the live preview and optionally warns about missing or unused definitions. It uses the same linguistic engine described above to recognize inflected forms across all five supported locales.
For configuration keys, see Configuration Reference — Defined Terms.
How it works¶
-
Extraction: VIBE scans the rendered Markdown for heading lines matching the configured heading (e.g.,
## Definitions). Under each matching heading, paragraphs and list items that start with**bold text**are treated as definition entries. The bold text is the term; the full line is the definition. -
Tooltip injection: In the HTML preview, every occurrence of a defined term (including its inflected forms) is wrapped in a
<span class="defined-term">with a tooltip showing the definition. Occurrences inside<code>,<pre>,<a>, and inside the Definitions section itself are excluded. -
Validation (when
validate: true):- Forward check — Scans the document body for title-cased mid-sentence words that look like defined terms but have no definition. Produces a warning for each undefined candidate.
- Reverse check — Verifies that every term in the Definitions section actually appears somewhere in the document body. Any inflected form counts as a match. Produces a warning for unused terms.
Inflection rules by locale¶
Each locale generates a set of surface forms from the base term. For multi-word terms (e.g., "Service Level Agreement"), only the last word (head noun) inflects; the prefix is preserved verbatim.
| Locale | Forms generated |
|---|---|
en |
base, plural, possessive ('s) |
sv |
base, plural, definite singular, definite plural, possessive, +s |
de |
base, genitive (+s only — plural is omitted to avoid false forms) |
fr |
base, plural |
es |
base, plural |
When no language rules are available for a locale, only the base form is used.
German exception¶
All German nouns are capitalized, so the forward check (which looks for capitalized mid-sentence words) would produce excessive false positives. For locale: de:
- The forward check is disabled — capitalized words in the body are never flagged as missing definitions.
- The reverse check still runs — defined terms that don't appear in the document body are flagged.
The reverse check uses the German inflection rules (base + genitive) to match, so "Vertrag" in the Definitions section is satisfied by "Vertrags" appearing in the prose.
DOCX template support¶
For DOCX host templates, the extraction system works on Markdown-like text produced by the DOCX text extractor (extract_text_with_markers). Two prerequisites make this work:
- Heading styles must map to Markdown headings. VIBE recognizes built-in Word heading styles for English, Swedish, German, French, and Spanish. For custom styles (e.g.,
"Beslutsmening"), add them viaadditional_word_headingsin the config. - Bold formatting in DOCX runs is emitted as
**bold**Markdown markers, so definition entries with bold terms are correctly extracted.
Whitelist¶
The whitelist config key accepts a list of strings (case-insensitive) that should be ignored by the forward check. Use this for proper nouns that are naturally capitalized mid-sentence but are not defined terms:
term_definitions:
enable: true
validate: true
whitelist:
- United Nations
- European Union
- Service Desk # internal name, not a legal term
Components¶
When a template uses components ({{ insert() }}), the Definitions section may live in a component rather than the host template. During both preview rendering and startup validation, VIBE merges terms from the host and all components using host-first, first-occurrence-wins order. A term defined in the host is never overridden by the same term in a component.