Manual:Messages API

Jump to navigation Jump to search
i18n docs

MediaWiki messages can be used in the code through the Message class and its associated methods. For instructions on the messages themselves, and tips on how to add new messages, see Localisation and in particular Localisation#General use (for developers) .

Using messages in PHP[edit]

Warning Warning: Make sure you always use one of the output modes mentioned below

Here is a simple example:

$out = Xml::submitButton( wfMessage( 'submit' )->text() );

wfMessage() is a global function which acts as a wrapper for the Message class, creating a Message object. This example then invokes Message method text() which fetches the text of the 'submit' message in the current language, performs certain language transformations (such as gender and plural), and returns the unescaped message text.

Here is a more complex example using a message that takes a count and supports linguistic plural handling:

$out = Xml::label( wfMessage( 'numberofpages' )->numParams( $count )->text() );

The following sections explain the code.


Given a message like the following:

    "msg": "Values are $1, $2"

You pass parameters to messages that need them in several ways:

wfMessage( 'msg', 'param1', 'param2' )->plain();
wfMessage( 'msg' )->params( 'param1', 'param2' )->plain();
wfMessage( 'msg', array( 'param1', 'param2' ) )->plain();

The first approach is most common, use the second approach when mixing different types of parameters, and you can use the third to construct message objects dynamically from other data. There are different types of parameters:

wfMessage( 'msg' )->params( $username )->plain();
wfMessage( 'msg' )->rawParams( $link )->plain();
wfMessage( 'msg' )->plaintextParams( $userInput )->plain();

wfMessage( 'msg' )->numParams( $count )->plain();
wfMessage( 'msg' )->durationParams( $duration )->plain(); // since MW 1.22
wfMessage( 'msg' )->expiryParams( $expiry )->plain(); // since MW 1.22
wfMessage( 'msg' )->timeperiodParams( $period )->plain(); // since MW 1.22
wfMessage( 'msg' )->sizeParams( $size )->plain(); // since MW 1.22
wfMessage( 'msg' )->bitrateParams( $bitrate )->plain(); // since MW 1.22
Normal message substitution parameter.
Substitutes the parameter after the message has been otherwise processed; this means that these parameters are not available to parser functions, nor are they escaped if escaping output format is used (see below). Make sure you escape them properly yourself.
Like rawParams(), but does escaping. It is useful when you pass user input that may contain wikitext that should not be parsed.

Each function from the second group formats the value in a specific way before the substitution. numParams() must be used if the message uses {{PLURAL:}}. In some cases you might not want to use it even though you have a number, for example a revision id. The other functions correspond to Language functions formatDuration, formatExpiry, formatTimePeriod, formatSize and formatBitrate, and are just shorthands for calling them directly.


To override the language in which you want the message, there is one method and one shortcut for the common case of using wiki content language. In the latter case you can use either a language code or a language object. The usual language fallback chains apply, so the actual message you get may be in a different language than requested, if a translation does not exist.

wfMessage( 'message-key' )->inContentLanguage();
wfMessage( 'message-key' )->inLanguage( $lang );

Output modes and escaping[edit]

The Message class, and thus the object returned by wfMessage(), has five output modes:

  • plain(): returns the message text as-is; only parameters are substituted[1]
  • text(): transforms the message text (MessageCache::transform() which transforms all '{{}}', e.g., plurals), but neither escapes nor sanitizes
  • escaped(): same as 'text', but also escapes it for use in HTML
  • parse(): parses the message text from wikitext to HTML and sanitizes (MessageCache::parse() which calls the Parser)
  • parseAsBlock(): the output is wrapped in a block level HTML element, if not already, similarly to OutputPage::addWikiMsg

Remember that Html:: functions escape everything fed into them, so use the text() format with those to avoid double escaping. Hence the most common output format is text(). Also, make sure to use parse() or parseAsBlock() if the message has wikitext in it, otherwise the wikitext will just be escaped and output as plain text.

When using wfMessage() or $this->msg(), you should always specify an output type. text() is appropriate when you're outputting it through addWikiText().

Which output mode to use[edit]

Generally speaking, the most common modes you will use are ->parse() and ->text(). You use ->parse() in most places where html markup is supported, and you use ->text() in places where the content is going to become html escaped or html markup is not supported.

Some common cases:

  • If you are putting the message in the text part (third argument) of Html::element use ->text(). You may also consider using Html::rawElement() instead and using the ->parse() mode.
  • If you are putting in text (third argument) of Html::rawElement(), you should generally use ->parse().
  • If you are putting into the attributes (second argument) of Html::rawElement() or Html::element(), use ->parse()
  • If you are manually constructing html attributes, you should use ->escaped(). However you should never manually construct html attributes
  • For $out->addWikiText() where $out is an OutputPage object use ->text() or ->plain(). However consider if you would rather use $out->addWikiMsg instead.
  • For $out->addHTML() use ->parse()

Method chaining[edit]

Most Message methods return the current object, so you can conveniently call one after another to operate on an object before finally returning its text. This is called method chaining. Here is an example:

wfMessage( 'key' )
	->params( 'apple' )
	->numParams( $numOfApples )
	->setContext( $context )

Additional methods of printing messages[edit]

The general message function in MediaWiki is wfMessage. However, since in a message the value of magic words can depend on the context, there are various wrappers to this function, that automatically set the correct context.

OutputPage has a few methods that append directly to the generated output. The useful ones are:

$out->addWikiMsg( 'pageheader' );
$out->wrapWikiMsg( '<div class="error">\n$1\n</div>', [ 'someerrormessage', $user->getName() ] );

Both of the above parse the wikitext in the context of the current page before appending it to output buffer.

Classes extending ContextSource have a method msg that automatically sets the current context (language, current page etc.). It is therefore recommended to use $this->msg() for those classes, like special pages. Here is a non-exhaustive list of such classes:[2]

  • CategoryViewer
  • HTMLForm
  • LogEventsList
  • DifferenceEngine
  • OutputPage
  • IndexPager
  • ImageHistoryList
  • ApiBase
  • ChangesList
  • Skin
Warning Warning: The QuickTemplate class and its subclasses (BaseTemplate, VectorTemplate, MonoBookTemplate, UserloginTemplate, UsercreateTemplate) have a method named msg which is different from the one from ContextSource. In these classes $this->msg() will simply output the escaped text of the message.

Examples of correct usage:

wfMessage( 'key' )->numParams( 567 )->text();
$this->msg( 'key' )->numParams( 567 )->parse();

Examples of incorrect usage:

wfMessage( 'key', 345 )->parseInline(); # Number is not formatted correctly
$this->msg( 'key', 345 )->numParams( 234 )->plain() # Plural syntax is not converted in plain format

Using messages in JavaScript[edit]

See also ResourceLoader/Default modules#mediaWiki.message
Note: this page only deals with MediaWiki core. See the specific documentation instead for the jquery.i18n module.

Getting the messages to the client[edit]

To use the messages, we need to make sure that the messages are available at client side first. This can be done using either a ResourceLoader module (most common) or an API query from JavaScript (rare).

Using a ResourceLoader module[edit]

See also Manual:$wgResourceModules#Details
Note: This is the most common method of delivering messages. You should use this unless you have a good reason not to.

We are going to use ResourceLoader to make sure that the messages are available at the client side. For this, in your ResourceLoader modules, define the messages to be exported to the client side.

If you plan to use the mw.message(…).parse() to generate HTML from wikitext in interface messages, then it is important to load the mediawiki.jqueryMsg module.

Example (extension.json):

	"ResourceModules": {
		"ext.abuseFilter.edit": {
			"scripts": "ext.abuseFilter.edit.js",
			"messages": [
			"dependencies": [

Using an API query from JavaScript[edit]

Note: This is not a common way of loading messages. You should only use this if there is a good reason why you can't use the ResourceLoader module method above.

You can use the following code:

MediaWiki version:
// When: The 'mediawiki.api' module is loaded, and, the page is ready
$.when( mw.loader.using( [ 'mediawiki.api', 'mediawiki.jqueryMsg' ] ), $.ready )
    // Then: Load the messages that you need (if they are not yet loaded)
    .then( function() {
        return new mw.Api().loadMessagesIfMissing( [ 'january', 'february', 'march' ] );
    } )
    // Then: Do stuff with them
    .then( doStuff );

To get the messages in some language other than the UserLanguage language, use getMessages instead of loadMessagesIfMissing, and supply the target language as the "amlang" field of the optional second parameter, like so:

// When: The 'mediawiki.api' module is loaded. no need to wait for the page to be ready.
$.when( mw.loader.using( [ 'mediawiki.api' ] ) )
    // Then: get some messages in French (language code 'fr')
    .then( function() {
        return new mw.Api().getMessages( [ 'january', 'february', 'march' ], { amlang: 'fr' }  );
    } )
    // Then: Do stuff with them
    .then( doStuff );
// doStuff is a function that will receive as its first parameter an object that looks like so:
// { february: "février", january: "janvier", march: "mars" }

For older MediaWiki versions before 1.27, use the following:

/** @return instance of jQuery.Promise */
function loadMessages( messages ) {
	return new mw.Api().get( {
		action: 'query',
		meta: 'allmessages',
		ammessages: messages.join( '|' ),
		amlang: mw.config.get( 'wgUserLanguage' )
	} ).then( function ( data ) {
		$.each( data.query.allmessages, function ( i, message ) {
			if ( message.missing !== '' ) {
				mw.messages.set(, message['*'] );
		} );
	} );

loadMessages( [ 'january', 'february', 'march' ] ).then( doStuff );

Use of the messages[edit]

The messages defined in the above example will be available at client side and can be accessed by mw.message( 'message-key-name' ). Some examples

$( '<a>' ).prop( 'href', '#' ).text( mw.message( 'translate-msggroupselector-projects' ).text() );

We can also pass the dynamic parameters to the message (i.e. the values for $1, $2, etc.) as shown below.

$( '<div>' ).text( mw.message( 'translate-msggroupselector-view-subprojects', count ).text() );

Note how we are using [jQuery].text to automatically escape our output properly. If this is not possible, here are few other examples:

  • If using jQuery's .append, escape manually .append( '<li>' + mw.message( 'example' ).escaped() + '</li>' );
  • If manually building an html string, always escape the message by creating a message object and calling .escaped() (don't use mw.message().text() or the mw.msg shortcut):
    '<foo>' + mw.message( 'example' ).escaped() + '</foo>';

In the above examples, note that the message should be defined in an i18n file. If the message key is not found in any i18n file, the result will be the message key in curved angle brackets U+29FC/U+29FD (part of mathematical symbols), like '⧼message-key-foo⧽'. In older versions of MediaWiki, the message key was returned in ASCII angle brackets, like '<message-key-foo>', and this could generate invalid or fake HTML elements. In the case where the message key does not exists, the .exists() method of the returned message object will also return false instead of true.

To use a message that must not go through the parser (e.g. when passing JSON data as messages, or when the message will be used as preloaded text of a page), use:

mw.message( 'foobar' ).plain()

Format options[edit]

If you don't specify the output format, mw.message just returns a Message object. To output the message itself, you should specify an output format. The formats are mostly the same as in PHP side:

  • mw.message( 'foobar' ).plain() Returns the message text as-is; only parameters are substituted.
  • mw.message( 'foobar' ).text() Transforms the message text (all supported {{}} blocks are replaced with transformed results). See #Feature support in JavaScript for details of what is supported. For example, certain keywords ({{int:}} (but only without parameters), {{GENDER}}, {{SITENAME}} etc.) work, but tranclusion (e.g. {{MediaWiki:}}) and server-side Magic words such as {{NUMBEROFEDITS}} or {{ns:Project}} do not work,
  • mw.message( 'foobar' ).escaped() HTML escaped version of text.
  • mw.message( 'foobar' ).parse() Parses the message text from wikitext to HTML. This supports everything from text mode, as well as most links, and whitelisted HTML.
  • mw.message( 'foobar' ).parseDom() Like parse(), but returns a jQuery collection instead of a HTML string.

Warning: If the mediawiki.jqueryMsg module is not loaded, all of the above methods behave essentially like plain() with possible escaping.

Note: There is no equivalent of parseAsBlock. Where necessary, wrap the output in a block element yourself.


Parameters can be specified as additional arguments to mw.message(). They can be passed as strings or as DOM nodes / jQuery collections.

Unlike in PHP, wikitext in the parameters is not parsed. Effectively, all string parameters behave like plaintextParams().

DOM/jQuery parameters can be used to achieve the equivalent of rawParams().

There is no support for other parameter formats. You can format numbers before passing them as parameters using mw.language.convertNumber().

Feature support in JavaScript[edit]

Warning Warning: Wikitext support in JS messages requires the mediawiki.jqueryMsg module to be loaded, otherwise these features will be silently ignored.

JavaScript messages only support a small subset of wikitext syntax. Supported features include:

  • Internal links (except pipe trick)
  • Explicit external links (no auto-numbered and free links)
  • Parser functions PLURAL, GENDER, GRAMMAR, int, ns, formatnum, lc, uc, lcfirst, ucfirst
  • HTML tags which are allowed in wikitext (HTML must be well-formed)
  • HTML entities &#039;, &quot;, &lt;, &gt;, &amp;
  • The ‎<nowiki> tag

Notable wikitext syntax that is not supported::

  • Templates
  • All other parser functions and magic words
  • Modules (for example Module:String)
  • All other XML-like tags (extension tags)
  • Bold and italic ''', '' (use ‎<b>, ‎<i> instead)
  • Lists using *, # (use ‎<ul>/‎<ol>, ‎<li> instead)
  • Definition lists / indents using ;, : (use ‎<dl>, ‎<dt>, ‎<dd> instead)
  • Multiple paragraphs (use ‎<p> instead)
  • Comments <!-- -->

The doc-jqueryMsg template can be used to document such messages, to let translators know which wikitext restrictions apply.


The mw.msg() function is commonly used as a shortcut for mw.message().text().

Exporting messages through ResourceLoader callbacks[edit]

If you need to process a message on the server and send the result to the client (e.g. because you need to parse the message using parsing features that aren't supported in JS), you can do that with a package files callback in your ResourceLoader module. When you do this, take care to use $context->msg(), because using wfMessage() will cause errors.

Using messages in Lua[edit]

Modules written in Lua using Scribunto run similarly to templates and have access to MediaWiki messages. The MediaWiki Lua library includes the mw.message class for processing messages. Refer to the full Lua message library documentation for the full API. Here is a simple example:

local p = {}

function p.nmembers( frame )
	local nmembersMsg = 'nmembers' )
	nmembersMsg:numParams( 3 ) -- This ensures number localization
	-- Show the message in the language of the wiki. frame:preprocess expands the {{plural}} clause.
	return frame:preprocess( nmembersMsg:plain() )

return p

Notes about gender, grammar, plural[edit]

See also Localisation#Switches in messages…; the syntax itself is documented at Help:Magic words#Localization and related.

In general, GENDER, GRAMMAR and PLURAL magic words work identically in both PHP and JavaScript sides.

  1. You must use text, escaped, parse or parseAsBlock output formats for them to work.
  2. You need to pass the relevant parameter as normal parameter to the message.
    • The parameter is the number for PLURAL; the plain text or wikitext-escaped username for GENDER in PHP; the gender from preferences or a user object for GENDER in JavaScript (see below).
    • For enabling plural and correct number localization in PHP, you need to use numParams for the number, see also #Chaining.
    • For enabling plural and correct number localization in JavaScript, you need to use mw.language.convertNumber for the number

PLURAL syntax example[edit]

# Simple plural
'key' => '$1 crying {{PLURAL:$1|baby|babies}}'

GENDER in JavaScript[edit]

This needs explicit jqueryMsg, see #Using messages in JavaScript.

If you have a message, say, "message-key-gender-foo": "{{GENDER:$1|he|she|they}} created an article", in JavaScript, you can use it as given below:

mw.message( 'message-key-gender-foo', 'male' ).text(); // returns 'he created an article'
mw.message( 'message-key-gender-foo', 'female' ).text(); // returns 'she created an article'
mw.message( 'message-key-gender-foo', 'unknown' ).text(); // returns 'they created an article'

Instead of passing the gender directly, we can pass any "User-like" object with a gender option. For example, the current user object mw.user.

var user = mw.user; // current user
mw.message( 'message-key-gender-foo', user ).text(); // The message returned will be based on the gender of the current user.

If the gender passed is invalid or unknown, the gender neutral form will be used as defined for each language. Pass 'unknown' if you intentionally want the neutral form.

Finally, if you want to use the gender of the current user, you can pass an empty string:

// the following line illustrates the message content, you can run this snippet on developer console
mw.messages.set( 'message-key-gender-foo', '{{GENDER:$1|male|female|unknown}}' );
mw.user.options.values.gender = 'female'; // temporarily manipulate your gender preference
mw.message( 'message-key-gender-foo', '' ).text(); // return value depends on your gender preference

PLURAL in JavaScript[edit]

This needs explicit jqueryMsg, see #Using messages in JavaScript.

If you have a message, say 'message-key-plural-foo' => 'There {{PLURAL:$1|is|are}} $1 {{PLURAL:$1|item|items}}' , in JavaScript, you can use it as given below:

mw.message( 'message-key-plural-foo', count ).text();
// returns 'There is 1 item' if count = 1
// returns 'There are 6 items' if count = 6

Help with replacing deprecated wfMsg* functions[edit]

These functions were removed starting with MediaWiki 1.27 LTS.

The code using these functions often has incorrect escaping and other code quality issues, so it's also recommended to

  • replace all Xml:: functions with their Html:: equivalents, which make it easier to do the right thing;[3]
  • where possible, avoid globals and use msg() (see above);
  • replace htmlspecialchars() with ->escaped() where appropriate.
Code change Description
Instead of:
wfMsg( 'key' );


wfMessage( 'key' )->text();
Instead of:
wfMsgExt( 'key', SOME_FORMAT, 'apple' );


wfMessage( 'key', 'apple' )->SOME_FORMAT_FUNCTION();
The second parameter specifies the output mode, usually expressed as an array like array( 'escape' ) but sometimes just like 'escape': it needs to be replaced according to #Output modes and escaping, like ->escaped().
Instead of:
wfMsgExt( 'key', array( 'parse' ), 'apple' );


wfMessage( 'key', 'apple' )->parseAsBlock();
Use full parsing, and wrap the output in block-level HTML tags.
Instead of:
wfMsgExt( 'key', array( 'parseinline' ), 'apple' );


wfMessage( 'key', 'apple' )->parse();
Use full parsing. Parseinline is used because it is more useful when pre-building HTML. In normal use it is better to use OutputPage::(add|wrap)WikiMsg.
Instead of:
wfMsgExt( 'key', array( 'parsemag' ), 'apple', 'pear' );


wfMessage( 'key', 'apple', 'pear' )->text();
Places where HTML cannot be used. {{-transformation is done.
Instead of
wfMsgHtml( 'key', 'apple' );


wfMessage( 'key' )->rawParams( 'apple' )->escaped();
wfMsgHtml does not escape parameters: to get the same result you need to use rawParams; check that the parameter really is safe for html output. If the message is then output as HTML, you must use escaped() for security: it will escape the parameters too and that's not always wanted, although it doesn't matter e.g. when the parameter is a number.
Instead of:
wfMsgForContent( 'key' );


wfMessage( 'key' )->inContentLanguage()->text();
Get a message in the wiki's content language ($wgLanguageCode ).
Instead of:
wfMsgForContentNoTrans( 'key' );


wfMessage( 'key' )->inContentLanguage()->plain();
Get a message in the wiki's content language ($wgLanguageCode ) but don't transform the message.
Instead of:
wfEmptyMsg( 'key', $message = wfMsgForContent( 'key' ) );


wfMessage( 'key' )->inContentLanguage()->isBlank();
Checks if the 'key' message in the wiki's content language is empty. Often, isDisabled() is a more appropriate check and should be used instead.
Instead of:
wfMsgReal( $error['message'], $error['params'] );


There is no simple replacement, depends on parameters. Should never have been used in the first place.
Instead of:


There is no simple replacement, depends on parameters. Should never have been used in the first place.

See also[edit]


  1. While using this mode to display HTML content is possible, it is recommended to use wikitext and use the parse() mode to transform it into HTML.
  2. More in general, use $this->msg() in non-static functions of IContextSource objects.
  3. For instance Xml::tags() doesn't escape.