Mastering MediaWiki's Parser Functions for Dynamic Content
Why Parser Functions Matter More Than You Think
Ever walked into a wiki page and felt like the content was doing a little dance on its own? That's not magic; it's parser functions pulling the strings. I remember the first time I saw {{#if:{{{foo|}}}|yes|no}} in action – my brain did a double‑take, like “Whoa, the page just read my own template!”
Turns out, those tiny double‑curly braces are the backstage crew that lets MediaWiki react to data, user input, or even the time of day. If you’ve ever wanted a banner that says “Good morning” before 12 pm and “Good afternoon” after, parser functions are your ticket.
Getting Your Feet Wet: The Basics
Before we dive deep, let’s set the table with the most common functions. No fluff, just the nuts and bolts.
#if– basic conditional.#ifeq– equality test.#switch– multi‑branch selector.#expr– arithmetic and logical expressions.#vardefine/#var– store and retrieve temporary values.#invoke– call a Lua module (the heavyweight champ).
Simple “If” That Does More Than You Expect
Imagine you have a template for a “Featured Article” badge. You only want it to show up when the page belongs to the Featured category. A one‑liner does the trick:
{{#if:{{#showCategory:Featured}}|★ Featured|}}
Notice the empty string after the pipe – that tells MediaWiki “do nothing” if the condition fails. I once wrote it without the second pipe and the page threw a strange “Parser error” that made me think the server had a coffee shortage.
Equality Checks: #ifeq in the Wild
Equality isn’t just about numbers; strings matter too. Let’s say you have a biography template and you want to display “Born” or “Founded” depending on whether the subject is a person or an organization.
{{#ifeq:{{{type|person}}}|person|
'''Born:''' {{{birthdate|unknown}}}
|'''Founded:''' {{{founded|unknown}}}
}}
That little snippet reads: “If the type parameter equals person, show the birth line; otherwise, show the founded line.” Simple, yet it eliminates a whole extra template file.
#switch: When “If” Gets Too Long
Ever tried nesting three #ifs just to pick a colour? It looks like a pretzel.
Enter #switch. It’s the tidy cousin that lets you map a value to a result in a single, readable block.
{{#switch:{{{status|unknown}}}
|draft=Draft version – keep editing.
|review=Ready for peer review.
|published=Live on the site.
|unknown=Status not set.
}}
Notice the “fallback” line at the bottom – that’s what shows up if none of the keys match. I’ve seen newbies forget that and get a blank spot where the text should be. Oops!
#expr: Doing Math Without a Calculator
MediaWiki isn’t just a static encyclopedia; it can crunch numbers. Say you want to display the age of a person given their birth year.
{{#expr: {{#time:Y}} - {{{birthyear|0}}} }}
Here #time:Y returns the current year, then we subtract the supplied birthyear. If the birthyear isn’t set, it defaults to 0 – which, well, makes the result look like a futuristic year. I guess that’s a subtle reminder to fill out the field.
Storing Temporary Data: #vardefine and #var
Sometimes you need a value that’s used multiple times in a template. Redundancy isn’t just a code smell; it can also be a performance hit.
{{#vardefine:myScore|{{#expr: {{#time:U}} % 10}}}}
Score today: {{#var:myScore}}
That snippet grabs the current Unix timestamp, mods it by ten, and stores the result as myScore. Then we pull it out later. Handy for random‑ish displays, like a “Quote of the Minute” widget.
When Lua Takes Over: #invoke
If you’re feeling ambitious, ditch the wikitext for a Lua module. #invoke calls a function inside a .lua file stored in Module:. Here’s a quick example that formats a date in a friendlier way.
{{#invoke:DateFormatter|pretty|{{#time:U}}}}
And the Lua side (just a taste):
-- Module:DateFormatter
local p = {}
function p.pretty(frame)
local ts = tonumber(frame.args[1])
if not ts then return "Invalid timestamp" end
return os.date("%A, %d %B %Y", ts)
end
return p
Now the page prints “Wednesday, 02 October 2025” instead of a raw Unix number. It’s a bit of extra work, but the clarity payoff is worth it, especially for multilingual wikis where you want locale‑aware formatting.
Real‑World Use Cases: From Infoboxes to Navigation
Parser functions aren’t just academic exercises. They’re the glue behind many of the slick features you see daily.
- Infoboxes that adapt: Show a “retired” flag automatically when a person’s
deathdateis filled. - Dynamic navigation tabs: Highlight the current section based on
#ifchecks against{{FULLPAGENAME}}. - Permission‑aware content: Use
#if:{{#usergroups}}|...|...to hide admin‑only warnings. - Time‑sensitive notices: A banner that says “Event ends in {{#expr:{{#time:U}} - 1696000000}} seconds”.
One of my favourite tricks is a “view‑count” badge that increments each time a page loads. It uses #vardefine in combination with the PageViewInfo extension – a perfect illustration of how parser functions can talk to extensions seamlessly.
Common Pitfalls (And How to Dodge Them)
Even seasoned editors stumble over a few things:
- Missing pipes: Forgetting the separator in
#ifresults in “Parser error” that looks like a cryptic puzzle. - Whitespace matters:
#if:(notice the spaces) will never match a clean value. - Infinite loops: Using a template that calls itself via a parser function can blow up the parser stack. I’ve seen a page freeze for minutes before I realised the loop.
- Version incompatibility: Some functions, like
#vardefine, were only introduced in MediaWiki 1.35. If you’re on an older install, you’ll need a fallback.
Pro tip: always test your snippets in a sandbox page first. It’s cheaper than hunting down a broken navigation bar on the live site.
Performance Thoughts – When Too Much Is Too Much
Parser functions run on every page view, so a cascade of heavy #expr calculations can add up. In a high‑traffic wiki, you might notice the server lagging a bit if you’re pulling in dozens of time‑based expressions.
One workaround is to cache results in a Template: that’s only refreshed via a cron job. That way, the heavy lifting happens off‑peak, and the page just pulls a static value.
The Human Side: Why We Love (and Occasionally Hate) Them
Honestly, there’s a certain thrill when a page “just works” because you coaxed it with a clever #switch. It feels like solving a puzzle, a bit like putting together a jigsaw where the picture keeps changing based on the day.
But there’s also that moment when you realize a colleague edited a template and broke a dozen pages in one go. Ouch. That’s why good documentation (yes, read the official docs) and clear naming conventions matter. I once named a variable temp – a classic mistake, because another module also used temp, and they collided like two cars at a four‑way stop.
Where to Go From Here
If you’re itching to experiment, try these small projects:
- Build a “Random Quote” widget that pulls from a list using
#expr:{{#time:U}} % {{#arraycount:{{{quotes|}}}}}. - Create a “User greeting” that says “Welcome,
{{#ifuser:{{{username|}}}|{{{username}}}|Guest}}”. - Design a “Progress bar” that fills based on a numeric parameter, using
#exprto calculate the percentage.
Each of these will push you to combine different functions, and that’s where the real mastery happens – not just memorising syntax, but learning how they dance together.
Final musings
At the end of the day, parser functions are the unsung heroes of MediaWiki. They let a static wiki feel alive, responsive, and even a tad bit personal. You don’t need to be a full‑blown developer to harness them; a curious mind and a sandbox page are enough.
So next time you glance at a tidy infobox or a clever banner, tip your hat to the little # that made it happen. And if you ever get stuck, remember: the community is full of folks who’ve wrestled with the same quirks – a quick look at the examples page can be a lifesaver.