Filters: Multi-Language Content (v2)

Maintained by Picture of Iñaki Arenaza Iñaki Arenaza
This filter is a greatly simplified multi-language filter. It uses very simple non-HTML tags to mark multi-language blocks. Namely {mlang XX} {mlang} pairs, where XX is the Moodle short name for the language pack (i.e., en, fr, eu, es, es_mx, etc.) It uses the same tags as the filter_multilangsecond plugin (to be compatible with it), but there is one difference between the two. This filter allows standalone {mlang} tags that don't require adjoining alternative language tags. This makes the filter more flexible at the cost of potentially producing empty sets of tags.
811 sites
34 fans

To Install it manually

  • Unzip the plugin in the moodle .../filter/ directory.

To Enable it

  • Go to "Site Administration >> Plugins >> Filters >> Manage filters" and enable the plugin there.

To Use it

  • Create your contents in multiple languages.
  • Enclose every language content between {mlang NN} and {mlang} tags:
    {mlang XX}content in language XX{mlang}
    {mlang YY}content in language YY{mlang}
  • Where XX and YY are the Moodle short names for the language packs (i.e., en, fr, de, etc.)
  • Test it (by changing your browsing language in Moodle).

How it works

  • Look for "lang blocks" in the code.
  • For each "lang block":
    • If there are texts in the currently active language, print them.
    • Else, if there exists texts in the current parent language, print them.
    • Else, don't print any text inside the lang block.
  • Text outside of "lang blocks" will always be shown.

Definition of "lang block"

A lang block is any text (including spaces, tabs, linefeeds or return characters) placed between '{mlang XX}' and '{mlang}' markers. You can not only put text inside "lang block", but also images, videos or external embedded content. For example, this is a valid "lang block":

{mlang es}
First paragraph of text. First paragraph of text. First paragraph of text.

Second paragraph of text. Second paragraph of text. Second paragraph of text.

                   An image could go here

Third paragraph of text. Third paragraph of text. Third paragraph of text.

                   An embedded Youtube video could go here

Fourth paragraph of text. Fourth paragraph of text. Fourth paragraph of text.

One example in action

We create a label with the content shown in the following image:

Multi-Language content in Spanish, English, an language-independent content

The "lang block" tags are highlighted using blue boxes. You can see we have three pieces of content: the Spanish-only content (light yellow box), the language-independent content (light blue) and the English-only content (light red).

If the user browses the page with English as her configured language, she will see the common content (light blue box) and the English-only content (light red):

Multi-Language content when browsed in English

If the user browses the page with Spanish as her configured language, she will see the Spanish-only content (light yellow) plus the common content (light blue box):

Multi-Language content when browsed in Spanish


Screenshot #0
Screenshot #1
Screenshot #2


Picture of Iñaki Arenaza
Iñaki Arenaza (Lead maintainer)
Please login to view contributors details and/or to contact them

Comments RSS

Show comments
  • Picture of Iñaki Arenaza
    Tue, 25 Apr 2017, 2:41 PM
    Hi Nicolas,

    the issue is that the "Select the missing word" question type doesn't support adding formatting to the answers (see Which means it doesn't apply any of the enabled filters to the value you specify in the answer(s).

    That doesn't play very well with this filter. When the "Select the missing word" code displays the question, it applies the enabled filters to the question text, which includes the answer(s) values unfiltered (as the SELECT element values).That means we end up having nested multilang tags, which the filter doesn't support (supporting nested multilang tags in the general case is more difficult and would be more CPU intensive).

    You could patch the "Select the missing word" question type to add formatting (via filtering) to the anwers' values. You just need to change two lines of code. The first one is in question/type/gapselect/rendererbase.php, around line 99 (in Moodle 3.2). Look for a line that reads like this:

    $choice->text) . ']';

    and change it to:

    format_string($choice->text)) . ']';

    The second one is in question/type/gapselect/renderer.php, around line 60 (in Moodle 3.2). Look for a line that reads like:

    $selectoptions[$orderedchoicevalue] = $orderedchoice->text;

    and change it to:

    $selectoptions[$orderedchoicevalue] = format_string($orderedchoice->text);

    I created a quiz with this type of question, and after applying the patch, it behaved as expected.

  • Picture of Nicolas Ndalpe
    Wed, 26 Apr 2017, 1:56 PM
    Hi Iñaki,
    Thank you for your answer. Your solution fixes the question's rendering issues. The problem now is that Moodle consider the question as incomplete even though I answered it properly.

    My guess is that, when Moodle tries to grade the question, it doesn't call format_string before analyzing the question which leaves 2 placeholders - one x per language. Therefor Moodle expects 2 answers and set the question status as incomplete when it receives only one.

    Below is a var_dump() of the question at grading time.

    1 - We can see that the "textfragment" array contains the unfiltered question text.

    2 - The "places" property contains 2 keys. Does places = number of expected answer?
    * @var array place number => group number of the places in the question
    * text where choices can be put. Places are numbered from 1.
    public $places;

    3 - /moodle/question/type/gapselect/questiontypebase.php line 126:
    is this where we should add a few format_string()?
    especially before $question->places gets populated?

    4 - Is this the right place to talk about this issue?

    Thank you for your help

    object(qtype_gapselect_question)#151 (34) {
    ["places"]=> array(2) {
    [1]=> string(1) "1"
    [2]=> string(1) "1"
    ["textfragments"]=> array(3) {
    [0]=> string(141) "{mlang en}
    Alkyd Melamine Resin Paint uses cross-linking system by condensation reaction between alkyd resin and melamine resin. There are "
    [1]=> string(177) " type and acid curing type.

    {mlang}{mlang id}
    Cat Alkyd Melamine Resin menggunakan sistem cross-linking dari kondensasi antara alkyd resin dan melamine resin. Ada tipe "
    [2]=> string(30) " dan tipe acid.

    ["rightchoices"]=> array(2) {
    [1]=> int(1)
    [2]=> int(1)

    ["questiontext"]=> string(358) "{mlang en}
    Alkyd Melamine Resin Paint uses cross-linking system by condensation reaction between alkyd resin and melamine resin. There are 1 type and acid curing type.

    {mlang}{mlang id}
    Cat Alkyd Melamine Resin menggunakan sistem cross-linking dari kondensasi antara alkyd resin dan melamine resin. Ada tipe 1 dan tipe acid.


  • Picture of Nicolas Ndalpe
    Wed, 26 Apr 2017, 7:14 PM
    Hi Iñaki,
    Update on the above problem. I found this as a solution and it seems to be working fine. What do you think? Any suggestion to make the code better? Also, should I add an issue on github so it is included in the next Moodle version?

    Thank you

    line 158

    I changed:
    $bits = preg_split('/\[\[(\d+)]]/', $question->questiontext, null, PREG_SPLIT_DELIM_CAPTURE);


    $formatedQuestionText = format_string($question->questiontext);
    $bits = preg_split('/\[\[(\d+)]]/', $formatedQuestionText, null, PREG_SPLIT_DELIM_CAPTURE);
  • Tim at Lone Pine Koala Sanctuary
    Wed, 17 May 2017, 1:22 AM
    Since this is really a bug in qtype_gapselect, which is now in standard Moodle, it might be better if this discussion moved to an issue in the Moodle bug tracker
  • Picture of Nicolas Ndalpe
    Thu, 18 May 2017, 3:27 PM
  • Picture of Dario Roig Garcia
    Wed, 20 Sep 2017, 4:20 PM
    Hi. We are using the plugin at Universuty of Valencia and is amazing. Our users and finded one error.
    In Moodle 3.3.1 and multi-lang Contect (v2) 1.0.5.
    One. create a new question with multilang text in the answer option.
    Two. edit the question, and now in the question text and in the other options, you can see the value of option 3
    Here you can see some screenshots
  • Picture of Iñaki Arenaza
    Sat, 23 Sep 2017, 7:29 PM
    Hi Dario,

    I commented on the Github issue:
  • Richard Samson
    Tue, 17 Apr 2018, 4:49 PM

    We use this great plugin. Thank you!

    I want to report a possible incompatibility with the html button for the ATTO editor. We were having trouble with an issue:

    Our computing boffins have finally managed to find the incompatability (though not the underlying cause).

    It turns out that there seems to be some interference between the HTML toolbar button and the multilang2 toolbar button in ATTO.

    In the ATTO toolbar configuration dialogue, you have to load html before multilang2.

    In other words,

    other = fullscreen,preview,multilang2,html
    doesn't work
    other = fullscreen,preview,html,multilang2

    Is there a bug in the multilang2 code? Or somewhere else?

  • Picture of Iñaki Arenaza
    Fri, 20 Apr 2018, 5:30 AM
    Hi Richard,

    just to mention that this plugin (filter_multilang2) is *not* related to Atto in any way wink This is a filter plugin, and works irrespective of the editor you use to produce your content (Atto, TinyMCE or any other).

    The Atto multi-language plugin ( which is available at ) is the one you seem to be having trouble with. That plugin produces the markup that is later processed by this plugin, but otherwise are completely independent.

    Anyhow, I also co-maintain the Atto multi language plugin so I can try to help you debug your issue. We can either move the discussion to the Atto multi language plugin page, or you can send me a direct message here in

  • Picture of Bert van der Hooft
    Fri, 8 Jun 2018, 4:35 PM

    Is it possible to automatic link to activities which names are multilingual? Now not working.

  • Picture of Michael Milette
    Tue, 31 Jul 2018, 2:53 AM
    I haven't tried it Bert and there are a lot of dependencies however, I suspect that if you move the Multi-Language Content (v2) filter below the Activity names auto-linking filter, the activity names might get linked first and then the language filter will remove the extra languages. Be sure to only apply the {mlang} tags to the link's text, exactly as you specified it in the course's name. Don't put whole links in mlang tags. Let us know if it works.
  • Picture of Rheman Pessek
    Fri, 14 Sep 2018, 12:23 PM
    hi everyone,

    Great plugin,

    But how to translate course title ?

    best regard,

  • Picture of amandeep singh
    Thu, 20 Sep 2018, 2:56 AM
    I would love to know about this plugin and the procedure thank you mobdro apk
  • Picture of Jan Wohlgemuth
    Tue, 16 Oct 2018, 10:14 PM
    Dear Iñaki,

    do you thinking about extension your filter with something like default wording. In case, that you have content in EN and CZ for example, and user has selected some other language, he gets emptz string.

  • Picture of Стоян Дренски
    Thu, 21 Feb 2019, 11:34 PM
    Dear Iñaki, thank you for the beautiful and very useful plugin! We use it on a bilingual moodle 3.5 site with courses and glossary. The issue is with the bilingual glossary entries which do not show in the mouse- over tooltip as expected. So my question is: does the plugin work with tooltips showing content of glossary terms in the course text? In our case the tooltip is showing the full string with the mlang's instead of the respective language only.

1 2 3 4
Please login to post comments