Fandom Developers Wiki

I18n-js is a library for loading a script's messages, stored as JSON, ready for said script to use. Not only does it allow messages to be split out of the main code containing all the logic, it handles language fallbacks and basic parsing as well.


I18n page

To use I18n-js, you will need to set up your messages in the appropriate place and in the correct format. The message loader will expect your messages to be in a page such as MediaWiki:Custom-<PAGENAME>/i18n.json here on Dev Wiki, where <PAGENAME> should be the name of your script. The format of your messages should be as follows:

    "en": {
        "name": "value"
    "pl": {
        "name": "wartość"

Editing JSON can be difficult, however, even for veterans. The ideal way of creating an /i18n.json page is navigating to Special:BlankPage/I18nEdit/<PAGENAME>/en and utilizing the dedicated editor.

Importing the script

Once you're all set up, simply import MediaWiki:I18n-js/code.js into your script. There are a few ways to achieve this, but they generally fall into one of two categories:

1. Import the script using importArticles or other import function that provides no indication of when the script has finished loading. If you use this method, you can listen for the dev.i18n event using mw.hook:

// register the hook before the import to avoid race conditions
mw.hook('dev.i18n').add(function (i18n) {
    // i18n is a shortcut to

importArticle({ type: 'script', article: 'u:dev:MediaWiki:I18n-js/code.js' });

2. Import the script using a function that provides a callback, such as $.getScript. If you're using this method, you use the callback and access within:

    .done(function() {
        // access here

Loading your messages

Now that the script is loaded, you're ready to load your messages. This is achieved using the loadMessages method of which returns a jQuery promise that resolves with an instance of i18n:

// name is the PAGENAME part of
i18n.loadMessages(name).done(function (i18n) {
    // use your i18n instance here

This will also cache said instance in case you attempt to load the messages again for any reason. Note that this promise will never be rejected; if the i18n.json page doesn't exist or is not valid, the instance of i18n will contain no messages and a warning will be logged in the browser console.

The loadMessages method also accepts an optional options object as the second argument, which may include the following properties:

  • cacheAll: An array of message names for which translations should be cached for all languages. See §Message caching for details.
  • cacheVersion: The minimum message cache version requested by the loading script. See §Message caching for details.
  • language: Set a language for the script to consider as the user language, instead of the MediaWiki variable wgUserLanguage. This language will be set as the default language, and will also take place when calling useUserLang() or inUserLang(). If not set, the default language will be set to wgUserLanguage.
  • noCache: Never load the i18n messages from cache (this is not recommended for general use).

Message caching

Loaded messages will be cached in browser storage for up to two days after being loaded, in order to improve responsiveness on future page loads (as the script won't have to wait for messages to be loaded each time). However, this means that your script may use messages that are up to two days old. The cached messages also include a version number which defaults to 0 (zero).

If a new message is added in a script update, a cache refresh may be necessary to prevent missing messages before the two day cache expiry. To do this, you can use the cacheVersion option in your loadMessages call. If the cacheVersion option is used, it'll be compared to the cached version number, and if the cached version number is less than the requested version, the cache will be refreshed and the cached version number will be set to the requested version.

By default, the cache only keeps translations for the user's language (wgUserLanguage) and the wiki content's language (wgContentLanguage) in order to keep cache size low. If your script needs to use translations from other languages, you'll need to use the cacheAll option in your loadMessages call. This option should be set to an array of strings, each string being the name of a message that should be cached for all languages it has been translated into. This option can also be set to true to cache translations for all languages, though this is not recommended for general use.

i18n usage

i18n controls access to your individual messages as well as the language it tries to translate them into. It defines the following methods:

  • useContentLang(): Set the default language to the value of wgContentLanguage.
  • useUserLang(): Set the default language to the user language (the user language is the value of wgUserLanguage, unless set otherwise by the options parameter of loadMessages()).
  • inContentLang(): Set the language to the value of wgContentLanguage for the next message only.
  • inUserLang(): Set the language to the user language for the next message only.
  • inLang(code): Set the language to code for the next message only. This method is only functional if the cacheAll option has been configured - see §Message caching for details.
  • msg(message, arg1, arg2, arg3, ...): Create a Message instance representing the message in the closest language to the default language possible with any arguments substituted in. See §Message usage for details on how to use this.

Message usage

Message represents a translated message in the closest language to the default language set in the i18n instance as possible. If a translation could not be found in the requested language, then it will try a fallback language instead, until it falls back to English. If the English translation could not be found, then it will contain the name of the message wrapped in < ... >, e.g. <i18njs-Example-some-message>, where Example is the name of the script and some-message is the name of the message that could not be found.

If your message uses arguments, these should be specified in the form $n where n is a integer greater than 0, e.g, 'Hello, $1, my name is $2'.

There are three methods available for outputting the message stored in the Message instance:

  • plain(): This outputs the message as is with no further processing.
  • escape(): This outputs the message with any HTML characters escaped.
  • parse(): This outputs the message with all basic wikitext links converted into HTML and some locale-specific magic words parsed. It also supports the inline tags <i>, <b>, <em>, <strong> and <span> and the attributes title, style and class. Note that disallowed tags will be removed along with their contents, disallowed attributes will be removed and url('...') in style attributes will cause the entire style attribute to be removed. The following wikitext syntax is supported:
    • [url text]
    • [[pagename]]
    • [[pagename|text]]
    • {{PLURAL:count|singular|plural}} (more info)
    • {{GENDER:gender|masculine|feminine|neutral}} (more info)
      • Note that usernames aren't supported - the 'gender' argument should be either 'male', 'female', or anything else for neutral)

Each Message instance also has one property:

  • exists: true if a translation was found for the message, else false.

If inLang, inContentLang, or inUserLang are being used, you can also chain the message call:

// start with the user's language (let's say English)
i18n.msg('hello-world').plain(); // Hello World!

// output in the wiki's content language for one message only
i18n.inContentLang().msg('hello-world').plain(); // Bonjour le monde !

// and back to English again
i18n.msg('hello-world').plain(); // Hello World!

Editing your messages

JSON can be a bit tricky to edit, especially if you're unfamiliar with the syntax. To improve the editing experience, a dedicated editor for them has been created, available at Special:BlankPage/I18nEdit. For editor instructions, you can see its documentation page.

Overriding messages

Sometimes, an end-user may wish to customise a set of messages according to their own preferences or even for a site-wide installation. This can be achieved using the following:

// in a user or site.js file

// initialise the global objects used without overwriting any already there = || {}; = || {}; = || {};['EXAMPLE'] =['EXAMPLE'] || {};

// customise the desired messages['EXAMPLE']['some-message'] = 'My customised message';['EXAMPLE']['another-message'] = 'Another customised message';

EXAMPLE is the name used by the message loader to identify where to load the message from. For example, for the name I18nEdit, the page would be u:dev:MediaWiki:Custom-I18nEdit/i18n.json. Therefore to customise the messages of I18nEdit, you would use the following: = || {}; = || {}; = || {};['I18nEdit'] =['I18nEdit'] || {};['I18nEdit']['title'] = 'My new title';

To find the name of a message, the QQX language code trick can be used. For scripts using I18n-js, the text will be shown as (i18njs-Example-some-message), where Example is the name of the script and some-message is the name of the message. For example, the edit-language message used in I18nEdit would show (i18njs-I18nEdit-edit-language).


List of dependents using this library

Change log

(out of date - see code page history for full log)

07 December 2018
  • Added support for the GENDER magic word when parsing messages.
19 September 2018
  • Added message caching functionality.
28 August 2018
  • Removed support for inline comments in JSON pages.
16 August 2018
  • Fixed an XSS issue when parsing messages.
  • Added an exists property to Message instances.
  • Added support for the PLURAL magic word when parsing messages.
  • Added support for the qqx language code to show keys of used messages.
21 June 2018
  • Added support for temporary language changes on a per message basis.
01 June 2018
  • Added support for some inline tags and attributes when using Message.parse().
29 May 2018
  • Added message override support.
21 February 2017
  • Prevent the script loading multiples times and causing the cache to be lost.
16 February 2017
  • Switched to factory method instead of constructors.
  • Fixed argument handling to start at $1 instead of $0.
  • Fixed link parsing for absolute URLs.
15 February 2017
  • Improved fallback behaviour to mirror that of MediaWiki.
  • Added argument handling.
  • Added basic parsing functionality.
13 February 2017
  • Initial release.

See also

Text above can be found here (edit)