Setting Up Multi-Language Support in MediaWiki Using Translate Extension
Ever tried to read a wiki that suddenly switched from English to Japanese mid‑article?
It feels like walking into a café and finding the menu printed in three different scripts. That is the kind of delightful chaos you get when a MediaWiki instance starts serving content in more than one language—if you’ve set it up right, of course.
Why bother with multilingual wikis?
First off, the world isn’t monolingual. Communities that span continents (think Wikimedia Commons or any open‑source project) often have contributors who speak French, Swahili, or even Cherokee. Offering the interface and help pages in their native tongue isn’t just a nicety; it’s a bridge.
- Better onboarding for new editors.
- Reduced misunderstandings—no more “I thought that button meant something else”.
- Search engines love localized content, so your wiki might climb a few extra ranks.
That said, you don’t need a full‑blown translation platform like Crowdin. The Translate extension does the heavy lifting right inside MediaWiki.
Getting the Translate extension
Okay, grab a terminal. If you’re using the MediaWiki Docker image, pop into the container first; otherwise, just SSH into your server.
# Navigate to the extensions directory
cd /var/www/html/extensions
# Clone the Translate repo (as of 2025‑10‑01, version 2025.01 is stable)
git clone https://gerrit.wikimedia.org/r/mediawiki/extensions/Translate.git
cd Translate
git checkout REL1_43
Don’t forget to run composer update --no-dev if your wiki uses Composer for dependency management. (I’ve seen folks skip this step and then wonder why MessageGroup classes are missing.)
Basic configuration (the “quick‑and‑dirty” way)
Open LocalSettings.php and sprinkle in the following, preferably near the bottom so it doesn’t get overwritten by later upgrades.
// Enable Translate
wfLoadExtension( 'Translate' );
// Set the default language of the wiki (optional, defaults to $wgLanguageCode)
$wgDefaultUserOptions['language'] = 'en';
// Allow users to change interface language via preferences
$wgTranslateUseSandbox = true; // sandbox for translators
$wgTranslateEnableLanguageCodeAlias = true;
Save the file. Then, run the update script to create the needed tables.
php maintenance/update.php
When you reload Special:Version you should see “Translate” listed with a green checkmark. If not, double‑check file permissions—sometimes the web server can’t read the new files. I’ve been there.
Adding languages you actually want
By default MediaWiki ships with about 200 language codes, but you’ll probably only enable a handful. Head over to Special:LanguageSettings (you need admin rights). You’ll see a giant checklist—think of it like a supermarket aisle for languages.
- Check “French (fr)”, “Spanish (es)”, “Swahili (sw)”—or whatever your community needs.
- Hit “Save”. The interface UI now offers a language selector in the personal toolbar.
Tip: If you want the selector to appear at the very top of the page (instead of the user menu), add this to LocalSettings.php:
$wgHooks['SkinTemplateNavigation'][] = function ( &$skin, &$links ) {
$links['actions']['languages'] = [
'class' => 'mw-ui-icon',
'text' => wfMessage( 'translate-language-selector' )->text(),
'href' => SpecialPage::getTitleFor( 'LanguageSettings' )->getLocalURL(),
];
return true;
};
It’s a little hacky, but it works—just don’t blame me if future MediaWiki releases change the hook name.
Translating interface messages
Here’s where the real fun begins. The Translate extension lets you translate any MediaWiki message (those msg‑* strings you see in the UI). Open Special:Translate and you’ll be greeted by a tidy table of groups.
Pick a group, say “Core” for the core interface. Click “new translation”, select the target language, and start typing. The editor even offers suggestions from the global translatewiki.net repository—handy if you want to avoid reinventing the wheel.
Once you’re done, hit “Save”. The translation goes into the database and is instantly available to users who have selected that language. No need to clear caches (though you might want to purge Special:MyLanguage to be safe).
One little quirk: the “plural forms” field can be confusing. MediaWiki uses CLDR rules, and the Translate UI shows a dropdown like “one, other”. If you’re not sure, just pick “other” and let the system handle it—most languages will fall back gracefully.
Managing translation workflow
Translate isn’t just a one‑off edit box; it includes a tiny workflow engine. You can assign translators, reviewers, and even set deadlines. Here’s a quick cheat‑sheet:
- Groups → Permissions: Define who can translate what. By default, any registered user can propose translations, but only admins can approve.
- Special:TranslateReview: Review pending translations. It shows a diff view, so you can spot broken placeholders like
$1or{{PLURAL:$1|cat|cats}}. - Special:TranslationStash: A sandbox for translators to experiment without cluttering the live tables.
In practice, I keep a small “translation team” page on the wiki with contact details. When a new language is added, I ping the volunteers and point them to Special:Translate. It’s a bit like herding cats, but the community vibe makes up for the occasional chaos.
Integrating with UniversalLanguageSelector (ULS)
If you’re already using the UniversalLanguageSelector (highly recommended), the two extensions play nicely. ULS adds a fancy dropdown with flags, search‑as‑you‑type, and even language‑family grouping.
Just enable it in LocalSettings.php:
wfLoadExtension( 'UniversalLanguageSelector' );
$wgULSAnonCanChangeLanguage = true; // let anonymous users pick a language
Now your visitors can switch languages without logging in—great for public documentation sites.
Some pitfalls you might bump into
— Cache confusion: If you use $wgCachePages or a reverse‑proxy (Varnish, Cloudflare), remember to purge the cache after a major translation push. Otherwise users will keep seeing the old English strings.
— Message keys: Avoid renaming message keys after they’ve been translated. The system treats the key as the identifier; change it and all existing translations disappear. I’ve lost a weekend’s work because of a typo in msg‑welcome → msg‑welcom.
— Right‑to‑left languages: Arabic or Hebrew need extra CSS tweaks (direction: rtl;) for proper layout. The Translate UI itself handles it, but your custom skins might not.
Seeing it in action
Picture this: you open Special:MyLanguage on a fresh install, select “Français”, and the entire navigation bar morphs—“Main Page” becomes “Page principale”, “Recent changes” turns into “Modifications récentes”. Even the “Edit” button reads “Modifier”. It’s a small thing, but it says “welcome”.
Here’s a screenshot (well, an imagined one—replace with your own later):
<!-- Example UI snippet after language switch -->
<div id="p-namespace">
<a href="/fr/Main_Page">Page principale</a>
</div>
<div id="p-views">
<a href="/fr/Recentchanges">Modifications récentes</a>
</div>
Notice the URL path includes the language code (/fr/). That’s because the Translate extension rewrites links automatically when $wgTranslateUseSandbox is true. If you prefer “language‑agnostic” URLs, set $wgTranslateUseSandbox = false and rely on the language selector only.
Keeping translations fresh
When you upgrade MediaWiki (say from 1.42 to 1.43), new interface messages appear. To avoid a half‑translated UI, run the maintenance/refreshMessageCache.php script after the upgrade, then check Special:Translate for any “untranslated” flags. It’s a habit I’ve built into my deployment checklist.
Also, consider enabling the auto‑translation fallback for low‑traffic languages. It pulls machine‑generated strings from the global translatewiki.net project, giving users a rough translation until a human steps in. Not perfect, but better than an English‑only wall.
Final thoughts
Setting up multilingual support with the Translate extension isn’t rocket science, but it does require a few extra steps that many newcomers overlook. The payoff—an inclusive, globally‑readable wiki—far outweighs the occasional hiccup with caches or plural forms.