<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luca Mauri</title>
    <description>The latest articles on DEV Community by Luca Mauri (@lucamauri).</description>
    <link>https://dev.to/lucamauri</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F367124%2Fa3ffbc51-f0ca-4f87-90de-f379e69bf102.png</url>
      <title>DEV Community: Luca Mauri</title>
      <link>https://dev.to/lucamauri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucamauri"/>
    <language>en</language>
    <item>
      <title>Messages on Mediawiki sidebar with Javascript</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Fri, 26 Mar 2021 16:59:21 +0000</pubDate>
      <link>https://dev.to/lucamauri/messages-on-mediawiki-sidebar-with-javascript-46il</link>
      <guid>https://dev.to/lucamauri/messages-on-mediawiki-sidebar-with-javascript-46il</guid>
      <description>&lt;p&gt;This is the story of a seemingly simple and straightforward modification to a user interface that led me far away from where I started and that taught me lessons I'd like to share with the community here.&lt;/p&gt;

&lt;p&gt;During the development of LUA code for the Wiki I manage, I often needs to see raw data from my &lt;a href="https://data.wikitrek.org"&gt;custom Wikibase instance&lt;/a&gt;, thus presented in JSON format.&lt;br&gt;
Wikibase allows a very simple way of accessing JSON representation of any given item by accessing the &lt;em&gt;EntityData&lt;/em&gt; special page with the syntax&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/Special:EntityData/Q1.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every time the user needs to access this page is necessary to go to the list of special pages, or remember the syntax and manually write the URL taking note of the item's number.&lt;br&gt;
This is clearly inconvenient, so I looked for a better way to easily get the JSON I needed.&lt;br&gt;
The &lt;em&gt;sidebar&lt;/em&gt; of a Wikibase instance, under &lt;em&gt;Tools&lt;/em&gt; group, contains a link named &lt;code&gt;Concept URI&lt;/code&gt;, handy to quickly get the URI of the item in the main page. From here I took the idea of creating a link on the sidebar to easily reach the JSON content I needed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Easy start
&lt;/h2&gt;

&lt;p&gt;I was already familiar with the sidebar customization as &lt;a href="https://www.mediawiki.org/wiki/Manual:Interface/Sidebar"&gt;explained in Mediawiki website&lt;/a&gt;, but in the past I used to make &lt;em&gt;static&lt;/em&gt; modifications, like adding external links. In this case, on the contrary, I needed a way to dynamically generate a link and only for specific pages.&lt;/p&gt;

&lt;p&gt;By attentively reading &lt;a href="https://www.mediawiki.org/wiki/Manual:Interface/Sidebar#Add_or_remove_toolbox_sections_(JavaScript)"&gt;further that same document&lt;/a&gt; it became clear to me I could add a code fragment in &lt;code&gt;MediaWiki:Common.js&lt;/code&gt; file to programmatically generate the link. The code example basically does already what I wanted to, I simply had to add a code to get the &lt;a href="https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config"&gt;specific page information&lt;/a&gt;, like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgServer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgWikibaseItemId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgPageName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then generate the URL and call the function exactly like the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ModifySidebar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toolbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wgServer&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/wiki/Special:EntityData/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ItemName&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and that was it.&lt;br&gt;
It worked fine, it seemed I solved the problem in a few minutes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Just one question
&lt;/h2&gt;

&lt;p&gt;But then I asked myself: what about internationalization? The code example simply created a tag with the fixed text specified in &lt;code&gt;name&lt;/code&gt; parameter, but my Wikibase instance is normally accessed both in Italian and English, so it would ideally need multi-language support.&lt;/p&gt;

&lt;p&gt;Again, seemingly easy thing to do: MediaWiki provides a standard mechanism to use &lt;em&gt;messages&lt;/em&gt;: the code contains placeholders string only, while the actual content of the string is defined in the user interface.&lt;br&gt;
So I wanted to create a message called something like &lt;code&gt;t-menu-label&lt;/code&gt; and being able to customize it by writing text in the pages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MediaWiki:T-menu-label\it
MediaWiki:T-menu-label\en
MediaWiki:T-menu-label\de
and so on…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I originally looked at the &lt;a href="https://doc.wikimedia.org/mediawiki-core/master/js/#!/api/mw.Message"&gt;documentation on message handling&lt;/a&gt;, but, with that instructions, I was only able to handle messages &lt;em&gt;within the code&lt;/em&gt;.&lt;br&gt;
I couldn't find a way to let the user customize messages with the &lt;code&gt;MediaWiki:&lt;/code&gt; mechanism explained above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Look closer
&lt;/h2&gt;

&lt;p&gt;It unfortunately took me a lot of effort to understand that I should have used a different approach to the problem. In fact the method I needed to use was the one explained in &lt;a href="https://www.mediawiki.org/wiki/Manual:Messages_API#Using_an_API_query_from_JavaScript"&gt;the message documentation&lt;/a&gt;.&lt;br&gt;
When I first read it, I was under the impression that this only was necessary to load &lt;strong&gt;default&lt;/strong&gt; messages from MediaWiki core, so I discarded it as a way to use my own &lt;strong&gt;custom&lt;/strong&gt; message.&lt;br&gt;
I was wrong: this system can be used to load &lt;strong&gt;any&lt;/strong&gt; message from MediaWiki: if the one requested does not exist in MediaWiki core, then it can be created as a custom one as explained above.&lt;/p&gt;
&lt;h2&gt;
  
  
  The final solution
&lt;/h2&gt;

&lt;p&gt;With this new understanding, I was finally able to put together the needed code to achieve my desired result.&lt;br&gt;
Let's jump at it, with some comments.&lt;/p&gt;
&lt;h3&gt;
  
  
  Call it
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sideJSONMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;t-wb-json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sideJSONMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;when&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;using&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mediawiki.api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mediawiki.jqueryMsg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ready&lt;/span&gt; &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;mediaWiki&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Api&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;loadMessagesIfMissing&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tooltip-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;AddJSONLinkToSidebar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This fragment of code starts the whole chain of events by identifying the name of the event to load, check that all the APIs are loaded and then proceeding to read the said message.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;t-wb-json&lt;/code&gt; is both the name of the message and the element ID of the HTML tag we'll create, this follows the conventions already in use in the sidebar.&lt;br&gt;
So, the menu &lt;code&gt;Concept URI&lt;/code&gt; is identified by &lt;code&gt;t-wb-concept-uri&lt;/code&gt;, my custom menu: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;belongs to &lt;strong&gt;T&lt;/strong&gt;ools group&lt;/li&gt;
&lt;li&gt;pertains &lt;strong&gt;W&lt;/strong&gt;iki &lt;strong&gt;B&lt;/strong&gt;ase&lt;/li&gt;
&lt;li&gt;is about a &lt;strong&gt;JSON&lt;/strong&gt; data output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus &lt;code&gt;t-wb-json&lt;/code&gt;, in short.&lt;/p&gt;

&lt;p&gt;Beside &lt;code&gt;messageName&lt;/code&gt;, another message called &lt;code&gt;'tooltip-' + messageName&lt;/code&gt; will be loaded. This will be useful to further describe the menu item, as explain later below.&lt;/p&gt;
&lt;h3&gt;
  
  
  Check page type
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;AddJSONLinkToSidebar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgServer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgWikibaseItemId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgCanonicalNamespace&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wgPageName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;

    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;PageName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wgPageName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nameSpace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wgCanonicalNamespace&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;nameSpaceList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Property&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Lexeme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameSpaceList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nameSpace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ItemName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;PageName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;AddItemToSidebar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toolbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;messageName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;wgServer&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/wiki/Special:EntityData/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ItemName&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With &lt;code&gt;mw.config.get&lt;/code&gt; we can obtain all the useful information about the Wikibase instance and the current context.&lt;br&gt;
All these data are needed to create the link, but &lt;em&gt;first&lt;/em&gt; of all is necessary to check that the page actually represent an &lt;strong&gt;item&lt;/strong&gt;, otherwise the JSON output would be meaningless and then non-existent.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Update 2021-04-01&lt;/strong&gt;&lt;br&gt;
I wrote a better code to check for the page type. The previous iteration used to analyze the substring for the text &lt;code&gt;item&lt;/code&gt;, now I make use of &lt;code&gt;wgCanonicalNamespace&lt;/code&gt; to programmatically check the page namespace in more consistent way.&lt;/p&gt;


&lt;h3&gt;
  
  
  Do the job
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;AddItemToSidebar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;languages&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-lang&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toolbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-tb&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;section&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ul&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;aNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;liNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;aNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nx"&gt;aNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;aNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tooltip-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="nx"&gt;liNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;aNode&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;liNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;liNode&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// let's just ignore what's happened&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;First of all, the function identifies the proper UL object by using the name of the section and then referencing the first DIV. Then a new LI is created to contain the A link.&lt;/p&gt;

&lt;p&gt;All the magic happens in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;aNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and in&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;aNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tooltip-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;idName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the &lt;em&gt;text&lt;/em&gt; of the link is set by reading the message loaded in the first fragment of code, above.&lt;br&gt;
In the same way, another message with the same label prefixed by &lt;code&gt;tooltip-&lt;/code&gt; (again, loaded above in the first step) is assigned to &lt;code&gt;title&lt;/code&gt; attribute: this will thus be shown as a tool-tip on mouse over.&lt;/p&gt;

&lt;p&gt;Finally, the node is given the same name as the message as &lt;code&gt;id&lt;/code&gt; attribute, for naming consistency, and all the element are properly concatenated into the DOM.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting the text
&lt;/h2&gt;

&lt;p&gt;Now that the code is ready, it is necessary to set the proper text for the messages. Remember that the code will ask Mediawiki engine for two messages called &lt;code&gt;t-wb-json&lt;/code&gt; and &lt;code&gt;tooltip-t-wb-json&lt;/code&gt;: if they are not set, a placeholder will be shown.&lt;/p&gt;

&lt;p&gt;To fill them, let's simply create two pages named &lt;code&gt;MediaWiki:T-wb-json&lt;/code&gt; and &lt;code&gt;MediaWiki:Tooltip-t-wb-json&lt;/code&gt;. Their content will become the label and the tool-tip of the link, respectively.&lt;br&gt;
This will work in the wiki's primary languages, but additional languages can simply be set by using subpages with the ISO code of the language, so we can create the pages&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MediaWiki:T-wb-json/it
MediaWiki:T-wb-json/de
MediaWiki:T-wb-json/fr
…
MediaWiki:Tooltip-t-wb-json/it
MediaWiki:Tooltip-t-wb-json/de
MediaWiki:Tooltip-t-wb-json/fr
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and fill them with the text in the proper language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experiment more
&lt;/h2&gt;

&lt;p&gt;This experience taught some interesting lessons about the inner workings of MediaWiki messages interface: a seemingly easy code actually hides a lot of complexity in research.&lt;/p&gt;

&lt;p&gt;Another lesson I learnt is to experiment more and don't stop where I &lt;em&gt;think&lt;/em&gt; the point is, because sometimes the point is somewhere, as I saw here.&lt;/p&gt;

&lt;p&gt;Finally, I must unfortunately point out again that MediaWiki documentation is fragmented and not always very clear to the final user.&lt;/p&gt;

</description>
      <category>mediawiki</category>
      <category>javascript</category>
      <category>wikibase</category>
      <category>json</category>
    </item>
    <item>
      <title>Auto-updating field in CorelDraw</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Wed, 17 Feb 2021 22:35:30 +0000</pubDate>
      <link>https://dev.to/lucamauri/auto-updating-field-in-coreldraw-3kk9</link>
      <guid>https://dev.to/lucamauri/auto-updating-field-in-coreldraw-3kk9</guid>
      <description>&lt;p&gt;It is common feature of several applications to have so-called &lt;em&gt;fields&lt;/em&gt;: small chunk of text that shows contestual data. Common examples are current date, number of page or file name: thigs that we often print in header or footer of documents.&lt;br&gt;
This is a functionality so commond that we take it for granted in all applications.&lt;/p&gt;

&lt;p&gt;On great use of them is to auto update the &lt;em&gt;Title block&lt;/em&gt; in technical drawings.&lt;br&gt;
Below a common example of a block containing date, filename and layout name: all these data are predefined fields in applications such as AutoCAD, so it's very easy to add them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tTAecBLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8ncvk47jig6s0gpxf68g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tTAecBLm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8ncvk47jig6s0gpxf68g.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In other design software these fields does not exists, so it is necessary to came up with a custom solution. In this case I will replicate the behaviour of a AutoCAD Title block in CorelDraw. I am going to use VBA so the same logic might apply to other applications with the appropriate modification to syntax.&lt;/p&gt;
&lt;h2&gt;
  
  
  When to run it
&lt;/h2&gt;

&lt;p&gt;First of all it is necessary to decide when to trigger the update. I resolved to do this right before saving and printing. This way the data on the block are updated in the stored version of the file and on paper.&lt;/p&gt;

&lt;p&gt;So, in the VBA editor, I modified the &lt;code&gt;BeforeSave&lt;/code&gt; and &lt;code&gt;BeforePrint&lt;/code&gt; events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Private&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt; &lt;span class="nf"&gt;Document_BeforePrint&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;Call&lt;/span&gt; &lt;span class="n"&gt;UpdateTextFields&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt;

&lt;span class="k"&gt;Private&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt; &lt;span class="nf"&gt;Document_BeforeSave&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ByVal&lt;/span&gt; &lt;span class="n"&gt;SaveAs&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;ByVal&lt;/span&gt; &lt;span class="n"&gt;FileName&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;Call&lt;/span&gt; &lt;span class="n"&gt;UpdateTextFields&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The function
&lt;/h2&gt;

&lt;p&gt;The first step is to store the names of the field in an array of string.&lt;br&gt;
Then the procedure iterates among all the pages to search for the appropriate text boxes in the whole document.&lt;br&gt;
Once found one of the box, the content is updated according to the name (and, by extension, to the type) of the box.&lt;br&gt;
Here's the full code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Private&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt; &lt;span class="nf"&gt;UpdateTextFields&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;CurrPage&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;Page&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;CurrShape&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;Shape&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;CurrText&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;Variant&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;Output&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TextDate"&lt;/span&gt;
    &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TextPageName"&lt;/span&gt;
    &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"TextFileName"&lt;/span&gt;

    &lt;span class="k"&gt;For&lt;/span&gt; &lt;span class="k"&gt;Each&lt;/span&gt; &lt;span class="n"&gt;CurrPage&lt;/span&gt; &lt;span class="ow"&gt;In&lt;/span&gt; &lt;span class="n"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Pages&lt;/span&gt;
        &lt;span class="k"&gt;For&lt;/span&gt; &lt;span class="k"&gt;Each&lt;/span&gt; &lt;span class="n"&gt;CurrText&lt;/span&gt; &lt;span class="ow"&gt;In&lt;/span&gt; &lt;span class="n"&gt;Texts&lt;/span&gt;
            &lt;span class="k"&gt;Set&lt;/span&gt; &lt;span class="n"&gt;CurrShape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CurrPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Shapes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FindShape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CurrText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;If&lt;/span&gt; &lt;span class="k"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;CurrShape&lt;/span&gt; &lt;span class="ow"&gt;Is&lt;/span&gt; &lt;span class="k"&gt;Nothing&lt;/span&gt; &lt;span class="k"&gt;Then&lt;/span&gt;
                &lt;span class="k"&gt;Select&lt;/span&gt; &lt;span class="k"&gt;Case&lt;/span&gt; &lt;span class="n"&gt;CurrText&lt;/span&gt;
                    &lt;span class="k"&gt;Case&lt;/span&gt; &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Short Date"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;Case&lt;/span&gt; &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CurrPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;
                    &lt;span class="k"&gt;Case&lt;/span&gt; &lt;span class="n"&gt;Texts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ActiveDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FileName&lt;/span&gt;
                &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Select&lt;/span&gt;
                &lt;span class="n"&gt;CurrShape&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Story&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;
            &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;If&lt;/span&gt;
        &lt;span class="k"&gt;Next&lt;/span&gt;
    &lt;span class="k"&gt;Next&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function looks in all the document's pages the three textbox named as in the array. If the text exists, then it will replace the content with the proper value.conta&lt;/p&gt;

&lt;p&gt;Apart from the obvious code, a point of interest here is the property &lt;code&gt;Text.Story&lt;/code&gt; that actually contains the text.&lt;/p&gt;

</description>
      <category>vba</category>
      <category>coreldraw</category>
      <category>corel</category>
      <category>technicaldrawing</category>
    </item>
    <item>
      <title>System.Text.Json in action with practical example in VB.net</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Sun, 16 Aug 2020 11:35:19 +0000</pubDate>
      <link>https://dev.to/lucamauri/system-text-json-in-action-with-practical-example-in-vb-net-1256</link>
      <guid>https://dev.to/lucamauri/system-text-json-in-action-with-practical-example-in-vb-net-1256</guid>
      <description>&lt;p&gt;XML is almost 25 years old and it is now a format that is widely-known to the point that also non tech-savvy people have at least a vague notion of it. The format was originally meant to encode documents in a format that is, of course, machine-readable, but that is &lt;em&gt;friendly&lt;/em&gt; enough to also be &lt;em&gt;human&lt;/em&gt;-readable.&lt;br&gt;
It has been criticised for its complexity and the difficulty to exchange data structure between application.&lt;/p&gt;

&lt;p&gt;For this reason, the format known as &lt;em&gt;JavaScript Object Notation&lt;/em&gt; (JSON) came to prominence as a less verbose (albeit less human-readable as well) alternative for data interchange.&lt;br&gt;
In this article I am going to show the creation of a JSON data structure to be used to programmatically create (or modify) an item on a WikiBase instance using the &lt;a href="https://www.mediawiki.org/wiki/Wikibase/API"&gt;WikiBase API&lt;/a&gt; with VB.net.&lt;/p&gt;
&lt;h2&gt;
  
  
  JSON in .NET
&lt;/h2&gt;

&lt;p&gt;Before &lt;em&gt;NET Core 3.0&lt;/em&gt; and &lt;em&gt;.NET Framework 4.7.2&lt;/em&gt; using JSON in .NET was much more complicated than, say, XML. The choices were to use the somewhat limited &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.web.script.serialization.javascriptserializer"&gt;&lt;code&gt;JavaScriptSerializer&lt;/code&gt; class&lt;/a&gt;, that was specifically designed for AJAX-enabled applications, or move to the popular &lt;a href="https://www.newtonsoft.com/json"&gt;Json.net&lt;/a&gt; library.&lt;br&gt;
Starting with the above-mentioned versions, however, .NET &lt;em&gt;finally&lt;/em&gt; started to offer a serious implementation of classes intended for JSON manipulation.&lt;br&gt;
This has been announced in the .NET Blog, in a post called &lt;a href="https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/"&gt;Try the new System.Text.Json APIs&lt;/a&gt; that I suggest you read if you like to know more about the implementation.&lt;br&gt;
In the rest of this article I will show you a practical use of this new component.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;For a project of mine, I need to massively create and edit items into a WikiBase-enabled MediaWiki installation. WikiBase is the extension that powers &lt;a href="https://wikidata.org"&gt;WikiData&lt;/a&gt;, but can be used on custom wiki site as well.&lt;br&gt;
Any WikiBase-equipped site (WikiData included, of course, if you are wondering) allows interaction through &lt;a href="https://www.mediawiki.org/wiki/Wikibase/API"&gt;WikiBase-specific API&lt;/a&gt;.&lt;br&gt;
To programmatically access and edit MediaWiki content I already used the excellent &lt;a href="https://sourceforge.net/projects/dotnetwikibot/"&gt;DotNetWikiBot framework&lt;/a&gt; so I decided to expand it, using its already existing infrastructure to add WikiBase-specific functions (work is still underway on this project, but I will eventually release it as opensource, ideally &lt;a href="https://sourceforge.net/p/dotnetwikibot/discussion/572544/thread/0b21ca9609/"&gt;integrating it&lt;/a&gt; into existing code).&lt;/p&gt;

&lt;p&gt;Data into WikiBase are easily accessible as a JSON formatted data by accessing the &lt;em&gt;EntityData&lt;/em&gt; special page like, for instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.wikidata.org/wiki/Special:EntityData/Q96482610.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When using the API, JSON data are of paramount importance to create or edit entities or part of them. Thus, handling JSON into my .NET application was crucial.&lt;/p&gt;

&lt;p&gt;My first task was to create a set of Properties into the WikiBase instance, so I needed to use the &lt;a href="https://www.wikidata.org/w/api.php?action=help&amp;amp;modules=wbeditentity"&gt;&lt;code&gt;wbeditentity&lt;/code&gt;&lt;/a&gt; module following the example&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a new property containing the json data, return full entity structure&lt;br&gt;
&lt;code&gt;api.php?action=wbeditentity&amp;amp;new=property&amp;amp;data={"labels":{"en-gb":{"language":"en-gb","value":"Propertylabel"}},"descriptions":{"en-gb":{"language":"en-gb","value":"Propertydescription"}},"datatype":"string"}&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;data&lt;/code&gt; parameter containing the JSON data.&lt;/p&gt;
&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;My application is a form-based one as I need to easily interact with the interface and be able to read and store results in various controls.&lt;br&gt;
So first of all I needed to add the &lt;code&gt;System.Text.Json&lt;/code&gt; (in contrast, this library is already part of the .NET Core 3.0) via the &lt;a href="https://www.nuget.org/packages/System.Text.Json"&gt;NuGet package&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This library allows object serialization, but this is too complex for my needs, as I would prefer manipulating the DOM without the need of creating corresponding classes in my code. While the solution might seem less elegant than having the full JSON structure created as .NET structure in classes and then simply &lt;em&gt;serialize&lt;/em&gt; them into JSON with a single command, the reality is that the sheer code needed to create all the classes would have been much more than the one needed to directly handling the JSON DOM.&lt;br&gt;
That being said, it remains the fact that JSON serializer is very useful and might be object of a future article.&lt;/p&gt;
&lt;h3&gt;
  
  
  First steps
&lt;/h3&gt;

&lt;p&gt;So the first steps to me were to familiarize with the &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.text.json.utf8jsonwriter"&gt;&lt;code&gt;Utf8JsonWriter&lt;/code&gt;&lt;/a&gt; method so I started converting the &lt;a href="https://gist.github.com/terrajobst/336da6ae0a327bef113c1325710164f0#file-sample9-cs"&gt;C♯ example&lt;/a&gt; to the following VB.net example:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Pay special attention at the &lt;code&gt;Writer.Flush()&lt;/code&gt; method that can easily be overlooked, but that is critical for the stream to be filled with actual data.&lt;br&gt;
As this worked as intended, I could proceed with the final version of the subroutine&lt;/p&gt;
&lt;h3&gt;
  
  
  The practical code
&lt;/h3&gt;

&lt;p&gt;In order to create a &lt;em&gt;Property&lt;/em&gt; in Wikibase you need to provide JSON data as a parameter to the API call to set the &lt;code&gt;labels&lt;/code&gt; (in the proper language), the related &lt;code&gt;descriptions&lt;/code&gt; and &lt;code&gt;[datatype](https://www.wikidata.org/wiki/Help:Data_type)&lt;/code&gt; defining the type of the data the property will contain.&lt;/p&gt;

&lt;p&gt;An example would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"datatype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"labels"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Label"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Etichetta"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"descriptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Description"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Descrizione"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With labels and descriptions in English and Italian.&lt;/p&gt;

&lt;p&gt;I started by creating an helper class like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Class&lt;/span&gt; &lt;span class="nc"&gt;LabelsWithDescription&lt;/span&gt;
    &lt;span class="k"&gt;Public&lt;/span&gt; &lt;span class="k"&gt;ReadOnly&lt;/span&gt; &lt;span class="k"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;Culture&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;Public&lt;/span&gt; &lt;span class="k"&gt;ReadOnly&lt;/span&gt; &lt;span class="k"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;Label&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;Public&lt;/span&gt; &lt;span class="k"&gt;ReadOnly&lt;/span&gt; &lt;span class="k"&gt;Property&lt;/span&gt; &lt;span class="nf"&gt;Description&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;

    &lt;span class="k"&gt;Sub&lt;/span&gt; &lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;Me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Culture&lt;/span&gt;
        &lt;span class="k"&gt;Me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;
        &lt;span class="k"&gt;Me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Class&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Please &lt;strong&gt;note&lt;/strong&gt; that this class cannot be serialized as it is: it holds all the necessary information, but not in the right structure. So it will &lt;em&gt;only&lt;/em&gt; help creating the structure. As mentioned above, creating the proper structure in VB and then serialize it would have been more complicated and time consuming in comparison to writing the DOM directly. At least this is the case for the current example, of course this depends on the situation and the reader must evaluate this on a per-case basis.&lt;/p&gt;

&lt;p&gt;Let's start to initialize the objects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Sub&lt;/span&gt; &lt;span class="nf"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IndentOutput&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;WriterOption&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;JsonWriterOptions&lt;/span&gt;

    &lt;span class="k"&gt;With&lt;/span&gt; &lt;span class="n"&gt;WriterOption&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Indented&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;IndentOutput&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;With&lt;/span&gt;

    &lt;span class="n"&gt;MemStream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MemoryStream&lt;/span&gt;
    &lt;span class="n"&gt;JSONWriter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;Utf8JsonWriter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MemStream&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WriterOption&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Sub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are creating here&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;Utf8JsonWriter&lt;/code&gt; that actually format and writes data&lt;/li&gt;
&lt;li&gt;its &lt;code&gt;WriterOption&lt;/code&gt; (needed to chose if indent the cose for readability, or minify-it with no spaces) and&lt;/li&gt;
&lt;li&gt;the &lt;code&gt;MemoryStream&lt;/code&gt; holding result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An now, finally, the function doing the job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Function&lt;/span&gt; &lt;span class="nf"&gt;PrepareNewItemData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ItemLabels&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Of&lt;/span&gt; &lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt;
    &lt;span class="k"&gt;With&lt;/span&gt; &lt;span class="n"&gt;JSONWriter&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteStartObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"datatype"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DataType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteStartObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"labels"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;For&lt;/span&gt; &lt;span class="k"&gt;Each&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt; &lt;span class="ow"&gt;In&lt;/span&gt; &lt;span class="n"&gt;ItemLabels&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteStartObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteEndObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;Next&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteEndObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteStartObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"descriptions"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;For&lt;/span&gt; &lt;span class="k"&gt;Each&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt; &lt;span class="ow"&gt;In&lt;/span&gt; &lt;span class="n"&gt;ItemLabels&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteStartObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Culture&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteEndObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;Next&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteEndObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteEndObject&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;With&lt;/span&gt;
    &lt;span class="k"&gt;Return&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MemStream&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="k"&gt;End&lt;/span&gt; &lt;span class="k"&gt;Function&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first couple of commands basically start writing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"datatype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The tricky parts comes afterwards where the method &lt;code&gt;.WriteStartObject("labels")&lt;/code&gt; output the fragment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"labels"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;in the JSON structure, allowing other content to be added to this "node".&lt;br&gt;
The two &lt;code&gt;For Each&lt;/code&gt; basically uses the same strategy to create an Object with the name of the language and the related &lt;em&gt;Labels&lt;/em&gt;, in the first cycle, and &lt;em&gt;Descriptions&lt;/em&gt;, in the second cycle.&lt;/p&gt;

&lt;p&gt;The final &lt;code&gt;.WriteEndObject()&lt;/code&gt; basically closes the whole data fragment and the very &lt;em&gt;important&lt;/em&gt; &lt;code&gt;.Flush()&lt;/code&gt; commits actual data to the stream that can be converted to string with &lt;code&gt;.GetString&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we can put everything to work with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight vb"&gt;&lt;code&gt;&lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;JSONTest&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;JSONEditor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;Dim&lt;/span&gt; &lt;span class="nv"&gt;LabelsList&lt;/span&gt; &lt;span class="ow"&gt;As&lt;/span&gt; &lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Of&lt;/span&gt; &lt;span class="n"&gt;JSONEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;LabelsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;JSONEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Label"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;LabelsList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;New&lt;/span&gt; &lt;span class="n"&gt;JSONEditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LabelsWithDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Etichetta"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Descrizione"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;MessageBox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;JSONTest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PrepareNewItemData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LabelsList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The output will be&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"datatype"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"labels"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Label"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Etichetta"&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;&lt;span class="nl"&gt;"descriptions"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"it"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Descrizione"&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;our intended JSON payload as above, but in minified format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;System.Text.Json&lt;/code&gt; is intended to be a easy-to-use, fast and integrated alternative to third-party JSON editors. This first adventure using it was a bit bumpy mainly because of the lack of detailed documentation and real examples on the internet, basically, I guess, because it is very new and not yet much used.&lt;br&gt;
Nevertheless it seems to me using is is really worth the minor pain of searching and experimenting.&lt;br&gt;
With this little story of mine I hope having helped other users to get start with it a little faster than I originally did.&lt;/p&gt;

</description>
      <category>vbnet</category>
      <category>json</category>
      <category>net</category>
      <category>wikibase</category>
    </item>
    <item>
      <title>Organize Interwiki and Sites in MediaWiki for best efficiency</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Sat, 25 Apr 2020 13:14:23 +0000</pubDate>
      <link>https://dev.to/lucamauri/organize-interwiki-and-sites-in-mediawiki-for-best-efficiency-36oe</link>
      <guid>https://dev.to/lucamauri/organize-interwiki-and-sites-in-mediawiki-for-best-efficiency-36oe</guid>
      <description>&lt;p&gt;Within the scope of MediaWiki, InterWiki links and the &lt;code&gt;sites&lt;/code&gt; table seems to have little in common, on the contrary in this article I will explain how a unified management of this two features can simplify working with both and clear the readibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anatomy of Interwiki
&lt;/h2&gt;

&lt;p&gt;Interwiki links are special links that allows to reach a page on a MediaWiki installation on any kind, such a custom one, or any Wikipedia site.&lt;br&gt;
This functionality works an a MediaWiki installation out of the box as several InterWiki links are defined by default. So you can immediately use links like these&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[wikipedia:Jean-Luc Picard|Jean-Luc Picard on English Wikipedia]]
[[memoryalpha:Jean-Luc Picard|Jean-Luc Picard on English ''Memory Alpha'']]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;to call pages on a foreign wiki – in this specific example, the English Wikipedia and the English Memory Alpha wikis – without using external links.&lt;/p&gt;

&lt;p&gt;You might notice something &lt;em&gt;strange&lt;/em&gt; in the above wikilinks: the prefixes followed by the colon symbol and then a title of the page.&lt;br&gt;
These prefixes instruct the MediaWiki installation to link a page in another site running MediaWiki, it has several advantages against a plain HTML external link, readability and the lack of "external website" warning on save, among the others.&lt;br&gt;
A complete explanation on interwiki links is &lt;a href="https://www.mediawiki.org/wiki/Manual:Interwiki"&gt;on the manual&lt;/a&gt;, for those interested. For the moment be content to know that the magic is done by the information matched with the &lt;code&gt;iw_prefix&lt;/code&gt; in the &lt;a href="https://www.mediawiki.org/wiki/Manual:Interwiki_table"&gt;&lt;code&gt;interwiki&lt;/code&gt; table&lt;/a&gt; in the database.&lt;br&gt;
Keep this information in mind for later in this article.&lt;/p&gt;
&lt;h2&gt;
  
  
  SiteLinks and &lt;code&gt;site&lt;/code&gt; table
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;site&lt;/code&gt; database table is of paramount importance for another feature called "SiteLinks". While you might be familiar with SiteLinks as a feature of WikiData, linking any &lt;em&gt;item&lt;/em&gt; to pages on sites of the Wikipedia family, in general terms those are special links coming from &lt;em&gt;any&lt;/em&gt; MediaWiki site with &lt;a href="https://wikiba.se"&gt;Wikibase&lt;/a&gt; installed to any other MediaWiki installation.&lt;/p&gt;

&lt;p&gt;SiteLinks needs first to be &lt;a href="https://www.mediawiki.org/wiki/Wikibase/Installation#Enable_Sitelinks"&gt;enabled and configured&lt;/a&gt; in the WikiBase &lt;em&gt;Repo&lt;/em&gt; with a string like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$wgWBRepoSettings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'siteLinkGroups'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s1"&gt;'wikipedia'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'mywikigroup'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'anothergroup'&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The "groups" mentioned in the above configuration are defined in the &lt;code&gt;sites&lt;/code&gt; table we discussed before: each groups contains one or more site with a unique identifier named &lt;code&gt;site_global_key&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, now that we know the two characters, we can proceed with their story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Organise things
&lt;/h2&gt;

&lt;p&gt;If you had a look at the database titles you might have noticed some common properties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;iw_prefix&lt;/code&gt; and &lt;code&gt;globalid&lt;/code&gt; both are kind of &lt;em&gt;unique identifiers&lt;/em&gt; for wiki&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iw_url&lt;/code&gt; and &lt;code&gt;page_path&lt;/code&gt; both points to the basic page address on the wikis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a clear advantage in using a unified notation for &lt;code&gt;iw_prefix&lt;/code&gt; and &lt;code&gt;globalid&lt;/code&gt; so the same prefix can be used both in InterWiki and SiteLinks.&lt;br&gt;
So I resolved to create a kind of &lt;em&gt;master table&lt;/em&gt; of sites I wanted to use in my wiki, that looked like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;globalid / iw_prefix&lt;/th&gt;
&lt;th&gt;group&lt;/th&gt;
&lt;th&gt;page_path / iw_url&lt;/th&gt;
&lt;th&gt;iw_api&lt;/th&gt;
&lt;th&gt;file_path&lt;/th&gt;
&lt;th&gt;languagecode&lt;/th&gt;
&lt;th&gt;description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;enma&lt;/td&gt;
&lt;td&gt;wikia&lt;/td&gt;
&lt;td&gt;&lt;a href="https://memory-alpha.fandom.com/wiki/%241"&gt;https://memory-alpha.fandom.com/wiki/$1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://memory-alpha.fandom.com/api.php"&gt;https://memory-alpha.fandom.com/api.php&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://memory-alpha.fandom.com/%241"&gt;https://memory-alpha.fandom.com/$1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;td&gt;Memory Alpha (inglese)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;enwiki&lt;/td&gt;
&lt;td&gt;wikipedia&lt;/td&gt;
&lt;td&gt;&lt;a href="https://en.wikipedia.org/wiki/%241"&gt;https://en.wikipedia.org/wiki/$1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://en.wikipedia.org/w/api.php"&gt;https://en.wikipedia.org/w/api.php&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://en.wikipedia.org/w/%241"&gt;https://en.wikipedia.org/w/$1&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;en&lt;/td&gt;
&lt;td&gt;Wikipedia (inglese)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I then wrote a small utility to extract data from this table (which I organized in a &lt;code&gt;|&lt;/code&gt;-separated CSV file for simplicity) and create three thing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;a group of SQL statement to insert interwiki prefixes as &lt;a href="https://www.mediawiki.org/wiki/Manual:Interwiki#Single_line"&gt;explained in the manual&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;a XML file &lt;a href="https://www.mediawiki.org/wiki/Manual:Sites_table#Adding_a_new_site"&gt;to be imported&lt;/a&gt; in the &lt;code&gt;sites&lt;/code&gt; table with the maintenance script &lt;code&gt;importSites.php&lt;/code&gt;. This is not the only way to populate the &lt;code&gt;sites&lt;/code&gt; table, but in my experience I found it to be the easiest one&lt;/li&gt;
&lt;li&gt;a code fragment in LUA to be used in &lt;a href="https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua"&gt;custom modules&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below you can see the result from the example above.&lt;br&gt;
The query for interwiki:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;interwiki&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iw_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_wikiid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_local&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_trans&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'enma'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://memory-alpha.fandom.com/wiki/$1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://memory-alpha.fandom.com/api.php'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;interwiki&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iw_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_wikiid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_local&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;iw_trans&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'enwiki'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://en.wikipedia.org/wiki/$1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'https://en.wikipedia.org/w/api.php'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The XML to be imported in &lt;code&gt;sites&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;sites&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.mediawiki.org/xml/sitelist-1.0/"&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;site&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"mediawiki"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;globalid&amp;gt;&lt;/span&gt;enma&lt;span class="nt"&gt;&amp;lt;/globalid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;group&amp;gt;&lt;/span&gt;wikia&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"page_path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;https://memory-alpha.fandom.com/wiki/$1&lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file_path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;https://memory-alpha.fandom.com/$1&lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;languagecode&amp;gt;&lt;/span&gt;en&lt;span class="nt"&gt;&amp;lt;/languagecode&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/site&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;site&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"mediawiki"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;globalid&amp;gt;&lt;/span&gt;enwiki&lt;span class="nt"&gt;&amp;lt;/globalid&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;group&amp;gt;&lt;/span&gt;wikipedia&lt;span class="nt"&gt;&amp;lt;/group&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"page_path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;https://en.wikipedia.org/wiki/$1&lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file_path"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;https://en.wikipedia.org/w/$1&lt;span class="nt"&gt;&amp;lt;/path&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;languagecode&amp;gt;&lt;/span&gt;en&lt;span class="nt"&gt;&amp;lt;/languagecode&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/site&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sites&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, the variable definition in LUA code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;VariableName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="n"&gt;enma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Memory Alpha (inglese)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;enwiki&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Wikipedia inglese'&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Now make them work together
&lt;/h2&gt;

&lt;p&gt;The source of information for the wiki pages is an &lt;em&gt;entity&lt;/em&gt; in WikiBase: the raw sitelinks data for the entity are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"entities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Q27"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

      &lt;/span&gt;&lt;span class="nl"&gt;"sitelinks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"enma"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"site"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enma"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jean-Luc Picard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"badges"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://memory-alpha.fandom.com/wiki/Jean-Luc_Picard"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"enwiki"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"site"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"enwiki"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jean-Luc Picard"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"badges"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://en.wikipedia.org/wiki/Jean-Luc_Picard"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I then created a function in a custom LUA module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SiteLinksInterwiki&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;AllLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;wikibase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getEntity&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;SiteLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sitelinks'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;Titles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;enma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Memory Alpha (inglese)'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;enwiki&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Wikipedia inglese'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SiteLink&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;pairs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SiteLinks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;TitleLabel&lt;/span&gt;

        &lt;span class="n"&gt;TitleLabel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Titles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SiteLink&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'site'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;SiteLink&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'site'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;AllLinks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="n"&gt;AllLinks&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"* [[:"&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="n"&gt;SiteLink&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'site'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="s2"&gt;":"&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="n"&gt;SiteLink&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="s2"&gt;"|''"&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="n"&gt;SiteLink&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="s2"&gt;"'']], "&lt;/span&gt; &lt;span class="o"&gt;..&lt;/span&gt; &lt;span class="n"&gt;TitleLabel&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;table.concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AllLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;string.char&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note this function cycles through all members of &lt;code&gt;sitelinks&lt;/code&gt; node and uses the &lt;code&gt;site&lt;/code&gt; field as prefix for the interwiki link and to determine the label to be shown after it.&lt;/p&gt;

&lt;h2&gt;
  
  
  💬Conclusion
&lt;/h2&gt;

&lt;p&gt;While this might seem a small details at first sight, in fact this trick greatly improves consistency and thus readability and code cleanliness.&lt;br&gt;
It also gave me the chance to deepen my knowledge of both mechanisms.&lt;/p&gt;

</description>
      <category>mediawiki</category>
      <category>interwikilink</category>
      <category>sitestable</category>
      <category>lua</category>
    </item>
    <item>
      <title>Put OAuthAuthentication back to work</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Sat, 18 Apr 2020 15:39:59 +0000</pubDate>
      <link>https://dev.to/lucamauri/put-oauthauthentication-back-to-work-522a</link>
      <guid>https://dev.to/lucamauri/put-oauthauthentication-back-to-work-522a</guid>
      <description>&lt;p&gt;The MediaWiki extension &lt;a href="https://www.mediawiki.org/wiki/Extension:OAuthAuthentication"&gt;OAuthAuthentication&lt;/a&gt; allows a user to login on a wiki delegating authentication to another one using the extension &lt;a href="https://www.mediawiki.org/wiki/Extension:OAuth"&gt;OAuth&lt;/a&gt;.&lt;br&gt;
The power of this extension is that allows us to run multiple wikis in a single family without asking the user to create user for each one of them. In the extreme situation, it even allows to delegate the login from any custom wiki to the most used wiki: Wikipedia.&lt;br&gt;
By the way, &lt;a href="https://oauth.net/"&gt;OAuth&lt;/a&gt; is the technology used by the foundation to allow &lt;em&gt;single-sign-on&lt;/em&gt; on the several sites of the Wikipedia family.&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Unfortunately OAuthAuthentication extension suffer from some issues: in particular, since MediaWiki version 1.34, it cannot be used out of the box because of some unsolved incompatibilities with part of the code in the MediaWiki core that were deprecated since the extension was originally created.&lt;br&gt;
There is already an effort to modify it to put it back to work as explained &lt;a href="https://phabricator.wikimedia.org/T110460"&gt;in this &lt;em&gt;Phabricator&lt;/em&gt; ticket&lt;/a&gt;, but this is a long term solution: it looks it is in the working since years and not yet ready to ship.&lt;br&gt;
Since I needed teh extension up and running for a custom project of mine, I looked for a &lt;em&gt;ad-interim&lt;/em&gt; solution, which I found with some googling around and some copy and paste.&lt;br&gt;
The solution explained below is by no means elegant, it is not even a real &lt;em&gt;solution&lt;/em&gt;: is a &lt;em&gt;workaround&lt;/em&gt;.&lt;br&gt;
It looks it works in my environment so I thought about sharing it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Working around
&lt;/h2&gt;

&lt;p&gt;After having installed everything as explained in &lt;a href="https://www.mediawiki.org/wiki/Extension:OAuthAuthentication"&gt;extension's page&lt;/a&gt;, let's start by modifying the file &lt;code&gt;OAuthAuthentication/handlers/AuthenticationHandler.php&lt;/code&gt;: in function &lt;code&gt;doCreateAndLogin&lt;/code&gt; transform the code fragment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$exUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;addToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;wfGetDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;DB_MASTER&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setCookies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;addNewUserLogEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;wfResetSessionID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;\Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;newGood&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;into the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$exUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;addToDatabase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;wfGetDB&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;DB_MASTER&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setCookies&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;addNewUserLogEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s1"&gt;'create'&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Modified as per https://gerrit.wikimedia.org/r/#/c/mediawiki/extensions/OAuthAuthentication/+/251930/33/handlers/AuthenticationHandler.php    &lt;/span&gt;
    &lt;span class="c1"&gt;// wfResetSessionID();&lt;/span&gt;
    &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getRequest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;resetId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;\Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;newGood&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In function &lt;code&gt;doLogin&lt;/code&gt; transform the code fragment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nx"&gt;wfResetSessionID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;\Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;newGood&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;into the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// Modified as per https://gerrit.wikimedia.org/r/#/c/mediawiki/extensions/OAuthAuthentication/+/251930/33/handlers/AuthenticationHandler.php&lt;/span&gt;
    &lt;span class="c1"&gt;//wfResetSessionID();&lt;/span&gt;
    &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getSession&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;resetId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;\Status&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="na"&gt;newGood&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the commented code you can see &lt;a href="https://gerrit.wikimedia.org/r/#/c/mediawiki/extensions/OAuthAuthentication/+/251930/33/handlers/AuthenticationHandler.php"&gt;where I took&lt;/a&gt; the modification for the &lt;a href="https://gerrit.wikimedia.org/r/#/c/mediawiki/core/+/518327/"&gt;deprecated &lt;code&gt;wfResetSessionID()&lt;/code&gt; function&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another possible issue you may incur in is the one explained in &lt;a href="https://phabricator.wikimedia.org/T207351"&gt;this other Phabricator ticket&lt;/a&gt; that is also worth working-around.&lt;br&gt;
In file &lt;code&gt;OAuthAuthentication/specials/SpecialOAuthLogin.php&lt;/code&gt; let's modify the function &lt;code&gt;execute&lt;/code&gt;: the fragment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$wgUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nv"&gt;$lp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\LoginForm&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Call LoginForm::successfulCreation() on create, or successfulLogin()&lt;/span&gt;
    &lt;span class="nv"&gt;$lp&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;should become&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$wgUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Modified as per https://phabricator.wikimedia.org/T207351&lt;/span&gt;
    &lt;span class="c1"&gt;//$lp = new \LoginForm();&lt;/span&gt;
    &lt;span class="c1"&gt;// Call LoginForm::successfulCreation() on create, or successfulLogin()&lt;/span&gt;
    &lt;span class="c1"&gt;//$lp-&amp;gt;$method();&lt;/span&gt;

    &lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\ReflectionMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'\SpecialUserLogin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'successfulAction'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;setAccessible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;\SpecialUserLogin&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As mentioned, this is very dirty, but it is quick and makes the extension workable again till a more permanent solution (probably with a new release) is found.&lt;/p&gt;

&lt;p&gt;If you are interested in further development on this, keep an eye on the already mentioned &lt;a href="https://www.mediawiki.org/wiki/Extension:OAuthAuthentication"&gt;extension's page&lt;/a&gt; and &lt;a href="https://phabricator.wikimedia.org/T110460"&gt;Phabricator ticket&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mediawiki</category>
      <category>extension</category>
      <category>php</category>
      <category>oauthauthentication</category>
    </item>
    <item>
      <title>Learning how to share what you learnt</title>
      <dc:creator>Luca Mauri</dc:creator>
      <pubDate>Fri, 17 Apr 2020 14:50:01 +0000</pubDate>
      <link>https://dev.to/lucamauri/learning-how-to-share-what-you-learnt-3e7n</link>
      <guid>https://dev.to/lucamauri/learning-how-to-share-what-you-learnt-3e7n</guid>
      <description>&lt;p&gt;My main project at the moment is a custom MediaWiki installation that hosts a hyper-textual guide to &lt;em&gt;Star Trek&lt;/em&gt;. It is something similar to the widely-known &lt;em&gt;Memory Alpha&lt;/em&gt;, surely in a smaller size, but it is in italian language and based on a standard modern version of MediaWiki. Furthermore, this project is heavily integrated with &lt;em&gt;WikiBase&lt;/em&gt;, a substantial extension to MediaWiki that provides database-like capabilities and it is the cornerstone of open data for &lt;em&gt;Wikipedia&lt;/em&gt; being the base of &lt;a href="https://www.wikidata.org/wiki/Wikidata:Main_Page"&gt;&lt;em&gt;WikiData&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  MediaWiki and LUA
&lt;/h2&gt;

&lt;p&gt;Basic usage of data from WikiBase is very easy, but any complex access to data needs custom coding in LUA. LUA is provided as a language for customising MediaWiki through an &lt;a href="https://www.mediawiki.org/wiki/Extension:Scribunto"&gt;extension called &lt;em&gt;Scribunto&lt;/em&gt;&lt;/a&gt;. WikiBase comes with a LUA Scribunto interface that allows easy manipulation.&lt;br&gt;
&lt;a href="https://www.mediawiki.org/wiki/Extension:Wikibase_Client/Lua"&gt;There is a manual&lt;/a&gt; on how to use the LUA interface that lists and explain all the object model, but IMHO fails in providing enough examples.&lt;br&gt;
So I started the painful experience, so familiar to all developers, of trials and errors till I found a way to make everything work.&lt;/p&gt;

&lt;p&gt;While the LUA code I was writing was specific to my project, I started thinking it could also be made more generic and maybe useful to other users, so i thought a way to share it.&lt;br&gt;
Being on a public Wiki, the code was accessible to anyone (but editable only to members, just as a passing comment) so already &lt;em&gt;shared&lt;/em&gt;, in sense. Nevertheless, the truth is, in practical terms, that our wiki is about a niche product of a niche of the entertainment industry; incidentally the wiki is also written in italian, reducing its potential readership even more.&lt;br&gt;
I needed a better idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to share
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;WikiTrek&lt;/em&gt; is a &lt;a href="https://github.com/WikiTrek"&gt;GitHub "organization"&lt;/a&gt; already, so the first thing I thought was to publish the LUA code on a dedicated repository. At first I started to copy and paste the code manually, so each time I made a modification to LUA code, I copied and pasted it.&lt;br&gt;
It was very inefficient and prone to errors.&lt;/p&gt;

&lt;p&gt;A better approach would have been to transfer data automatically from the wiki pages to GitHub.&lt;br&gt;
First important thing was not to reinvent the wheel, so I started looking for a ready-to-use PHP library to interact with GitHub and found &lt;a href="https://github.com/KnpLabs/php-github-api"&gt;PHP GitHub API&lt;/a&gt; pretty soon. It is an excellent library to perform any kind of operations on GitHub using ready-made PHP classes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding the right way
&lt;/h2&gt;

&lt;p&gt;So I started playing around with &lt;em&gt;PHP GitHub API&lt;/em&gt; and, in a couple of hours (documentation and examples of that library might benefit from some work, but this is another story), I had a proof-of-concept small application to manipulate GitHub via that API.&lt;br&gt;
My original plan was to write a &lt;a href="https://www.mediawiki.org/wiki/Manual:Maintenance_scripts"&gt;MW Maintenance script&lt;/a&gt; and run it on the server periodically using &lt;em&gt;cron&lt;/em&gt; or maybe MW own scheduler.&lt;br&gt;
The more I looked into this solution, though, the more complicated it became.&lt;br&gt;
After a few days of alternatively banging my head against the problem and thinking about it, I came up with a different solution.&lt;/p&gt;

&lt;p&gt;I started looking into &lt;a href="https://www.mediawiki.org/wiki/Manual:Developing_extensions"&gt;&lt;em&gt;extension&lt;/em&gt; development&lt;/a&gt; and found out there is a class of extensions using &lt;a href="https://www.mediawiki.org/wiki/Manual:Hooks"&gt;&lt;em&gt;Hooks&lt;/em&gt;&lt;/a&gt; allowing to inject custom PHP code at certain event. Most prominent example of these events is &lt;a href="https://www.mediawiki.org/wiki/Manual:Hooks/PageContentSaveComplete"&gt;&lt;code&gt;PageContentSaveComplete&lt;/code&gt;&lt;/a&gt; and that was all I needed: by intercepting a page when it is saved, I could have taken the content to send it to GitHub.&lt;br&gt;
Bingo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the extension
&lt;/h2&gt;

&lt;p&gt;First step was to familiarise myself with the extension development: MediaWiki documentation on the topic is vast and – as unfortunately often happens with that project – not completely structured.&lt;br&gt;
I found the two most important thing to master:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the intricacy of &lt;a href="https://www.mediawiki.org/wiki/Manual:Extension_registration"&gt;Extension registration&lt;/a&gt; using the &lt;code&gt;extension.json&lt;/code&gt; file and&lt;/li&gt;
&lt;li&gt;the handling of custom settings via &lt;a href="https://www.mediawiki.org/wiki/Manual:Configuration_for_developers"&gt;configuration variables&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once I understood the basics of extension development, I had to tackle some issues about the on the working of the extension:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I wanted only &lt;em&gt;some&lt;/em&gt; pages to be transferred, so I found a way to select the pages belonging to &lt;code&gt;Module:&lt;/code&gt; namespace only&lt;/li&gt;
&lt;li&gt;All the pages with code on them ends up in the &lt;code&gt;Module:&lt;/code&gt; namespace, so I needed to select only specific pages, otherwise I would have copied code belonging to other extensions or template or whatever, most likely code non even written by contributors to the site. I resolved to do so by introducing a custom keyword to look for in the page.&lt;/li&gt;
&lt;li&gt;I implemented a mechanism to &lt;em&gt;not&lt;/em&gt; save the pages if the edit is marked as "Minor"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Firstly I hard-coded all of the above for testing purpose: by the end of the projects, I made all options user-customisable variables that can be handled in &lt;code&gt;Localsettings.php&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing words
&lt;/h2&gt;

&lt;p&gt;The result of all this effort is an extension that I called &lt;a href="https://github.com/lucamauri/PageToGitHub"&gt;&lt;em&gt;PageToGitHub&lt;/em&gt;&lt;/a&gt; (or &lt;em&gt;P2G&lt;/em&gt;, in brief). I don't expect this to be used by someone else as it address a very specific feature that is hardly to be found elsewhere.&lt;br&gt;
Nevertheless I am very satisfied with it because, apart of solving the original issue I had, the journey to create it helped me to improve my (otherwise &lt;em&gt;very&lt;/em&gt; limited) PHP skills and guided me to better understand inner MediaWiki mechanisms.&lt;br&gt;
Beside, of course, allowing me to write this post and start my humble contribution to DEV community.&lt;/p&gt;

</description>
      <category>mediawiki</category>
      <category>lua</category>
      <category>php</category>
      <category>github</category>
    </item>
  </channel>
</rss>
