Manual:Messages API
i18n docs: Localisation · Messages API · translatewiki.net · Language · Writing systems · Directionality · HOWTO training · Statistics/Checks |
See also Localisation for general guidelines and in particular Localisation#General use (for developers).
Contents |
Using messages in PHP [edit]
The message system in MediaWiki can seem complex at first, due to the number of features it has. These features are related to proper formatting and escaping of the output as well as supporting as many languages as possible. The three cases covering almost all cases are:
- plain: as-is, no processing at all except variable substitution
- text: light wiki-parsing, all parser functions and magic words are expanded ({{ }} constructs)
- parse: full wiki-parsing
Except for parse
which returns HTML that can be outputted as-is, all the other formats should be properly escaped depending on the context. Usually the context is HTML. There are many ways in which this escaping can happen.
![]() |
Make sure you always use one of the output modes mentioned below |
Handling messages [edit]
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 light wiki-parsing, 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.
Parameters [edit]
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' )->numParams( $count )->plain(); wfMessage( 'msg' )->rawParams( $link )-plain();
The first one is a normal message substitution parameter. The second one formats the number before substitution; if the message uses {{PLURAL:}} then you need to use this. In some cases you might not want to use numParams even though you have a number, for example a revision id. The third one substitutes the rawParams 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.
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 '{{}}')
- escaped() - same as 'text', but also escapes it (htmlspecialchars)
- parse() - parses the message text from wikitext to HTML (MessageCache::parse() which calls the Parser)
- parseAsBlock() - the output is wrapped in block level html element, if not already, similarly to OutputPage::addWikiMsg
Remember that most Xml:: and Html:: functions escape everything fed into them, so use text() format with those to avoid double escaping. Hence the most common output format is text().
Language [edit]
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 language code or language object. The usual language fallback chains apply, so the actual message you get may be in a different language than requested, if translation does not exist.
wfMessage( 'message-key' )->inContentLanguage(); wfMessage( 'message-key' )->inLanguage( $lang );
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 call chaining. Here is an example:
wfMessage( 'key' ) ->params( 'apple' ) ->numParams( $numOfApples ) ->setContext( $context ) ->inContentLanguage() ->parse()
Choosing message function [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 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>', array( 'someerrormessage', $user->getName() ) );
Both of the above parse the wikitext in the context of 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:
- CategoryViewer
- HTMLForm
- LogEventsList
- DifferenceEngine
- OutputPage
- IndexPager
- ImageHistoryList
- ApiBase
- ChangesList
- Skin
Suggestion for how to pass messages around [edit]
When you are building a new interface and need to pass messages from other parts of the code, consider using Message
objects for that. They are far more flexible than plain string message keys (no parameters!) or arrays of strings and message keys. Lots of old code does not yet accept Message objects.
Using messages in JavaScript [edit]
To use the messages, we need to use ResourceLoader to make sure that the messages are available at client side first. For this, in your ResourceLoader modules, define the messages to be exported to client side. It is important to note that loading the mediawiki.jqueryMsg module significantly changes the behavior of mw.message and mw.msg. Generally, you should always load jqueryMsg.
Abbreviated real example:
$resourcePaths = array( 'localBasePath' => __DIR__, 'remoteExtPath' => 'Translate' ); $wgResourceModules['ext.translate.groupselector'] = array( 'styles' => 'resources/css/ext.translate.groupselector.css', 'scripts' => 'resources/js/ext.translate.groupselector.js', 'position' => 'top', 'dependencies' => array( 'mediawiki.jqueryMsg', ), 'messages' => array( 'translate-msggroupselector-projects', 'translate-msggroupselector-search-placeholder', 'translate-msggroupselector-search-all', 'translate-msggroupselector-search-recent', 'translate-msggroupselector-load-from-all', 'translate-msggroupselector-view-subprojects', ), ) + $resourcePaths;
The messages defined in the above example will be available at client side and can be accessed by mw.messages( '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, escape manually by creating a message object and calling
.escaped()
(instead of themw.msg
shortcut ):
'<foo>' + mw.message( 'example' ).escaped() + '</foo>';
There are some more or less used aliases like gM
and mw.msg
that nowdays map to mw.message().text()
, but their use is either deprecated or discouraged.
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 angle brackets – like <message-key-foo>.
To use a message that is natively HTML and has no other logic or variables, such as MediaWiki:stub-threshold, use:
mw.message( 'stub-threshold' ).plain()
Raw html messages are highly discouraged.
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:}}, {{GENDER}}, {{SITENAME}} etc. work), but {{MEDIAWIKI:}} and server-side Magic words such as {{NUMBEROFEDITS}} or {{ns:Project}} do not.,mw.message( 'foobar' ).escaped()
HTML escaped version oftext
.mw.message( 'foobar' ).parse()
Parses the message text from wikitext to HTML. This supports everything fromtext
mode, as well as most links, and whitelisted HTML.
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 to an element yourself.
Feature support in JavaScript [edit]
- Mediawiki 1.19 onwards, the messages for JavaScript can contain PLURAL and GENDER directives.
- MediaWiki 1.20 onwards, the messages for JavaScript can contain GRAMMAR directive.
- MediaWiki 1.21 (1.21wmf8) onwards, the messages for JavaScript can contain uses of the INT directive.
- MediaWiki 1.21 (1.21wmf9) onwards, some FORMATNUM support is available, primarily localization for digits and decimal separators.
- MediaWiki 1.21 (1.21wmf10) onwards, messages can also have both wikilinks and external links. However, features like the pipe trick are not supported.
- MediaWiki 1.22 (1.22wmf2) onwards, the messages can have limited HTML. Currently <b> and <i> are supported.
The keywords are case insensitive, but uppercase is preferred.
Notes about gender, grammar, plural [edit]
In general, GENDER, GRAMMAR and PLURAL magic words work identically in both PHP and JavaScript sides.
- You must use
text
,escaped
,parse
orparseAsBlock
output formats for them to work. - You need to pass the relevant parameter (username for GENDER; number for PLURAL) as normal parameter to the message.
- For plural in PHP, you need to use
numParams
for the number, see also #Chaining.
- For plural in PHP, you need to use
JavaScript examples [edit]
If you have a message, say, 'message-key-gender-foo' => '{{GENDER:$1|he|she}} 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'
Instead of passing the gender directly, we can pass a User object - i.e. mw.User object with a gender attribute to mw.msg. For e.g., the current user object.
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 to mw.msg is invalid or unknown, gender neutral form will be used as defined for each language.
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
Deprecated wfMsg* functions [edit]
Code change | Description |
---|---|
Instead of:
wfMsg( 'key' ); Do: wfMessage( 'key' )->text(); |
|
Instead of:
wfMsgExt( 'key', array( 'parseinline' ), 'apple' ); Do: 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' ); Do: wfMessage( 'key', 'apple', 'pear' )->text(); |
Places where HTML cannot be used. {{-transformation is done. |
Instead of
wfMsgHtml( 'key', 'apple' ); Do: wfMessage( 'key' )->rawParams( 'apple' )->escaped(); |
wfMsgHtml does not escape parameters, so you need to use rawParams. Please double check that the parameter really is safe for html output. |
Instead of:
wfMsgForContent( 'key' ); Do: wfMessage( 'key' )->inContentLanguage()->text(); |
Get a message in the wiki's content language ($wgLanguageCode). |
Instead of:
wfMsgForContentNoTrans( 'key' ); Do: 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' ) ); Do: wfMessage( 'key' )->inContentLanguage()->isBlank(); |
Checks if the 'key' message in the wiki's content language is empty. |
Rationale [edit]
Problems with the deprecated message system:
- Many functions with many parameters are confusing
- The most common use case is not the simplest invocation
- The simple implementation is wrong (wfMsg)
- wfMsg replaces variables after {{-transform, does not parse nor escape
- When a fallback message is used, parsing in the wrong language can lead to really broken results. Think about a message in a language which has three plurals that falls back to English which has only two. In this case the English text is parsed as if it had three plurals. This also affects other language dependent stuff like grammar.
- The
replaceafter
directive affects all parameters, where it is usually needed only for some of them - The
parsemag
directive (or {{-transform,escape
,parse
,parseinline
, etc) is hard to get right
The suggested solution for all these problems is above, expect parsing in a wrong language, since that problem is much deeper.
Old wfMsgExt [edit]
- This section is outdated
wfMsgExt is a deprecated function within GlobalFunctions.php to retrieve the contents of a system message as listed in Special:Allmessages
- function wfMsgExt( $key, $options ) : string.
returned string is value of the specified system message for the currently active language.
$key string representing a valid message-id
$options is a string containing one of the following options (or an array containing one or more of these strings):
options | description |
---|---|
parse | parses wikitext to html |
parseinline | parses wikitext to html and removes the surrounding p's added by parser or tidy |
escape | filters message through php function htmlspecialchars |
escapenoentities | filters message through php function htmlentities - equivalent to htmlspecialchars, but allows entity references like through. |
replaceafter | parameters are substituted after parsing or escaping |
parsemag | transform the message using magic words |
content | fetch message for content language instead of interface; also can accept a single associative argument, of the form 'language' => 'xx': |
language | Language object or language code to fetch message for (overridden by content), its behavior with parser, parseinline and parsemag is undefined. |
See also [edit]
Notes [edit]
- ↑ While using this mode to display HTML content is possible, the translation team recommends using wikitext instead and using parse() mode to transform it into HTML.