Skip to content

MediaWiki Parser Functions — #if, #switch, #expr, #time, and Conditional Templates

DodaTech Updated 2026-06-26 11 min read

In this tutorial, you will learn about MediaWiki Parser Functions. We cover key concepts, practical examples, and best practices to help you master this topic.

Parser functions in MediaWiki are built-in programming constructs that add conditional logic, arithmetic, date formatting, and string manipulation to wikitext — transforming templates from static snippets into dynamic, intelligent components like those used across Wikipedia's infoboxes and navigation systems.

What You'll Learn

  • Using {{#if:}} for conditional content display
  • Using {{#switch:}} for multi-case selection
  • Performing calculations with {{#expr:}}
  • Formatting dates with {{#time:}}
  • Checking page existence with {{#ifexist:}}
  • Building a complete dynamic template

Why It Matters

Without parser functions, a template always shows the same content. With them, a template can decide what to display based on input. A "User Status" template can show "Online" in green or "Offline" in red. An "Age Calculator" template can compute years from a birth date. A "Navigation Box" template can show or hide sections based on whether the target page exists. Parser functions turn wikitext into a basic programming language.

Real-World Use

A DodaTech documentation wiki has a "Version Info" template that accepts a version number and displays release date, LTS status, and support end date. It uses #if to check whether the version is older than 3.0 (showing a "Legacy" warning), #switch to map version numbers to release dates, #expr to calculate years since release, and #time to format dates consistently.

Learning Path

flowchart LR
  A["12: Image & Media"] --> B["13: Transclusion"]
  B --> C["14: Parser Functions"]
  C:::current
  D["15: Subpages"]
  E["16: Redirects"]
  F["17: Categories"]

  C --> D --> E --> F

  classDef current fill#38bdf8,color#0f172a,stroke-width:2px

What Are Parser Functions?

Parser functions look like templates but are built into MediaWiki. They start with # and use a colon instead of a pipe for the first separator:

{{#if: condition | then-value | else-value }}

The colon separates the function name from its first argument. Pipes separate additional arguments.

#if — Conditional Display

{{#if:}} checks whether a string is non-empty and displays different content accordingly.

{{#if: {{{1|}}}
| The parameter was provided.
| No parameter was provided.
}}

If {{{1}}} has a value, the first line after the pipe is shown. If it is empty or not provided, the second line is shown.

{{#if: {{{online|}}}
| <span style="color:green;">Online</span>
| <span style="color:red;">Offline</span>
}}

A page using this template:

{{UserStatus|online=yes}}

Displays "Online" in green. Without the parameter, it shows "Offline" in red.

Important: #if checks if the string is non-empty. A value of 0 or false is still a non-empty string, so #if considers it true. For boolean logic, use #ifeq or #iferror.

#ifeq — String Equality

{{#ifeq: {{{format|}}} | pdf
| Show PDF download link
| Show HTML version
}}

This checks if the format parameter equals "pdf" exactly. Use this for template parameters that accept specific string values.

#ifexpr — Mathematical Condition

{{#ifexpr: {{PAGESIZE:Main Page}} > 5000
| Main Page is over 5KB
| Main Page is under 5KB
}}

This evaluates a mathematical expression and shows one of two values based on whether the result is non-zero. Use comparison operators: >, <, >=, <=, =, !=.

#iferror — Error Checking

{{#iferror: {{#expr: 1/0}} | Division by zero! | {{#expr: 1/0}} }}

This checks whether the first argument produces a MediaWiki error. If it does, the second argument is shown. If not, the third argument is shown.

#ifexist — Page Existence

{{#ifexist: Template:Infobox
| Template:Infobox exists
| Template:Infobox does not exist
}}

This checks whether a page exists on the wiki. It is useful for navigation templates that should only link to pages that have been created.

#switch — Multi-Case Selection

{{#switch:}} is like an if-else chain or a switch/case statement in programming.

{{#switch: {{{severity|info}}}
| error   = <span style="color:red;">Error</span>
| warning = <span style="color:orange;">Warning</span>
| info    = <span style="color:blue;">Info</span>
| #default = <span style="color:gray;">Unknown</span>
}}

If severity is "error", it shows "Error" in red. If "warning", it shows orange. If "info" or anything not listed, it shows the default.

The #default case catches all unspecified values. Without a default, unmatched values produce nothing.

Switch with Multiple Values per Case

{{#switch: {{{os|}}}
| windows | win | w = Windows
| mac | macos | darwin = macOS
| linux | unix = Linux
| #default = Other
}}

Multiple values on the same line (separated by pipes) all map to the same result. The template accepts "Windows", "win", or "w" and returns "Windows".

#expr — Mathematical Expressions

{{#expr:}} evaluates arithmetic expressions and returns the result.

{{#expr: 2 + 2 }}            Renders: 4
{{#expr: 10 / 3 }}           Renders: 3.3333333333333
{{#expr: 10 / 3 round 2 }}   Renders: 3.33
{{#expr: 2 ^ 10 }}           Renders: 1024
{{#expr: (5 + 3) * 2 }}      Renders: 16
{{#expr: pi * 5 ^ 2 }}       Renders: 78.539816339745

Supported operators:

  • Arithmetic: +, -, *, /, ^ (power)
  • Comparison: =, !=, <, >, <=, >=
  • Logical: and, or, not
  • Functions: abs, ceil, floor, trunc, round, ln, log, sin, cos, tan, pi

Practical Example: File Size Display

{{#expr: {{PAGESIZE:{{{page|Main Page}}}}}
    / 1024 round 1 }} KB

This displays the size of any page in kilobytes, rounded to one decimal place. The PAGESIZE magic word returns the content length in bytes.

#time — Date Formatting

{{#time:}} formats dates and timestamps.

{{#time: Y-m-d }}                       Renders: 2026-06-28
{{#time: l, F j, Y }}                   Renders: Sunday, June 28, 2026
{{#time: H:i:s }}                       Renders: 14:30:00
{{#time: r }}                           Renders: Sun, 28 Jun 2026 14:30:00 +0000
{{#time: Y }}                            Renders: 2026

Format codes (same as PHP date()):

  • Y — 4-digit year
  • y — 2-digit year
  • F — Full month name (January)
  • M — 3-letter month (Jan)
  • m — 2-digit month
  • d — 2-digit day with leading zero
  • j — Day without leading zero
  • l — Day of week (Sunday)
  • D — 3-letter day (Sun)
  • H — 24-hour hour
  • h — 12-hour hour
  • i — Minutes
  • s — Seconds
  • r — RFC 2822 date

Custom Timestamps

{{#time: Y-m-d | 2026-01-15 }}          Renders: 2026-01-15
{{#time: F j, Y | {{REVISIONTIMESTAMP}} }}  Renders: January 28, 2026

The second parameter to #time is a timestamp. Without it, the current time is used. You can pass any valid date string.

Practical Example: Age Calculator

{{#expr:
  {{#time: Y}} - {{{year|2020}}}
  - ({{#time: md}} < {{{month|01}}}{{{day|01}}} ? 1 : 0)
}} years old

This template calculates age from a birth year, month, and day. It subtracts one year if the current date is before the birthday this year.

#tag — XML Tags

{{#tag:}} generates XML-style tags programmatically.

{{#tag:syntaxhighlight|
function hello() {
    console.log("Hello, world!");
}
|lang=javascript
}}

This is how templates can generate <syntaxhighlight> blocks with dynamic content. The first parameter is the tag name, the second is the content, and additional parameters become attributes.

Putting It Together: A Dynamic Infobox

Let's build a "Product" infobox that uses all the parser functions we learned:

<includeonly>{| class="wikitable" style="float:right;width:300px;"
|+ {{{name|Product Name}}}
|-
{{#if:{{{version|}}}|
! Version
| {{{version}}}
|-
}}
{{#if:{{{release|}}}|
! Release Date
| {{#time: F j, Y | {{{release}}} }}
|-
}}
{{#if:{{{size|}}}|
! Size
| {{#expr: {{{size}}} / 1024 / 1024 round 1 }} MB
|-
}}
! Status
| {{#switch: {{{status|stable}}}
  | stable = <span style="color:green;">Stable</span>
  | beta   = <span style="color:orange;">Beta</span>
  | alpha  = <span style="color:red;">Alpha</span>
  | deprecated = <span style="color:gray;">Deprecated</span>
  | #default = Unknown
}}
|-
{{#ifexist: Template:Product_{{ROOTPAGENAME}}_Nav |
! Navigation
| {{Product_{{ROOTPAGENAME}}_Nav}}
|-
}}
|}</includeonly>
<noinclude>
== Usage ==
{{Product
|name=DodaSync
|version=2.1
|release=2026-06-01
|size=15728640
|status=stable
}}
</noinclude>

This template uses:

  • #if to hide rows when parameters are empty
  • #time to format the release date
  • #expr to convert bytes to megabytes
  • #switch to color the status text
  • #ifexist to conditionally include a navigation template

What You Learned

  • #if shows content based on whether a string is non-empty
  • #ifeq compares two strings for equality
  • #switch selects content from multiple cases
  • #expr evaluates mathematical expressions
  • #time formats dates with PHP-style format codes
  • #ifexist checks whether a page exists
  • Parser functions can be nested for complex logic

In the next lesson, you'll learn about subpages — a way to create parent-child page hierarchies for organized content.

Common Mistakes

| Mistake | Why It Happens | How to Fix | |---------|---------------|------------| | #if treats "0" as empty | #if checks for non-empty strings, and "0" is technically non-empty. However, an empty string is falsy. If you need to check for a zero number, use #ifeq. | Use {{#ifeq: {{{param|}}} | 0 | ... }} for exact comparison. | | #expr returns errors for invalid expressions | The expression contains unsupported operators or syntax | Check for valid operators. Use floor, ceil, or round to handle division results. Wrap in #iferror to handle gracefully. | | #time shows the wrong date | Timezone not configured | Set $wgLocaltimezone = 'UTC' or your timezone in LocalSettings.php. #time uses the server timezone. | | #switch does not match when it should | Leading or trailing whitespace in the value | Trim whitespace from parameters: {{#switch: {{{param|}}} }}. Spaces in parameter values can cause mismatches. | | Nested parser functions are hard to read | Complex logic in one line | Break into multiple template calls or use intermediate templates for sub-expressions. Deep nesting is confusing and error-prone. | | #ifexist slows down the wiki | Checking many pages per render | Use #ifexist sparingly. Each call checks the database. On a page with 50 #ifexist calls, rendering can be noticeably slow. | | Parser function output shows raw code | Syntax error in the function call | Check colons vs pipes. {{#if:condition|then|else}} is correct. A common mistake is {{#if|condition|then|else}} with pipe instead of colon. |

Practice Questions

  1. Write a parser function expression that displays "Over 100 KB" if the page size exceeds 102400 bytes, and "Under 100 KB" otherwise.
  2. Create a template called "SeasonalGreeting" that uses #switch to display a different greeting based on the current month: "Happy New Year" for January, "Spring is here" for March-May, "Summer vibes" for June-August, "Autumn leaves" for September-November, and "Happy Holidays" for December.
  3. How would you calculate and display a person's age given their birth year, month, and day as template parameters?
  4. Challenge: Build a "System Requirements" template that accepts three parameters: os, ram_mb, and disk_mb. The template should use #switch to display "Windows", "macOS", or "Linux" based on the OS abbreviation. Use #expr to convert RAM from megabytes to gigabytes (rounded to 1 decimal). Use #if to hide any row where the parameter is empty. Add a #ifexist check for a "System Requirements Notes" page and append a link if it exists.

FAQ

Can I create custom parser functions?

Yes, but it requires writing a MediaWiki extension in PHP. Custom parser functions are registered using the ParserFirstCallInit hook. The Scribunto extension (Lua) is often an easier alternative for complex logic.

How many parser functions can I nest?

There is no hard limit, but practical nesting depth is around 5-7 levels. Beyond that, the code becomes unreadable and hard to debug. Consider using Lua modules (Scribunto) for complex logic.

What is the difference between #if and #ifeq?

#if checks if a string is non-empty. #ifeq checks if two strings are equal. Use #if for existence checks (parameter provided or not). Use #ifeq for value comparisons (is the status 'active' or 'inactive').

Do parser functions work in the template namespace only?

Parser functions work anywhere wikitext is processed: templates, pages, and even in the File namespace description pages. However, they are most commonly used in templates where dynamic behavior is needed.

Can I use parser functions inside the VisualEditor?

VisualEditor has limited support for parser functions. Complex parser function syntax is best edited in the wikitext editor. VisualEditor can render the results but editing the logic requires switching to source mode.

Mini Project

Goal: Create a "System Info" template that displays dynamic server information.

  1. Create Template:SystemInfo with parameters: hostname, os, uptime_days, cpu_usage, ram_total_gb, ram_used_gb, status
  2. Use #if to hide rows where parameters are empty
  3. Use #expr to calculate RAM usage percentage: (ram_used_gb / ram_total_gb) * 100 round 1
  4. Use #switch to color the status: online=green, maintenance=yellow, offline=red
  5. Use #time to display the current date at the bottom: "Report generated on June 28, 2026"
  6. Use #ifexpr to show a warning when CPU usage exceeds 80%
  7. Create a test page that uses the template with real-looking data
  8. Add #ifexist to check for a "Server:{{hostname}}" page and link to it if it exists

What's Next

Parser functions give your templates intelligence. Now let's organize your wiki content with subpages — a hierarchy for related pages.

Continue to Lesson 15: Subpages — learn how subpages create parent-child relationships and automatic breadcrumb navigation.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro