User:Nikki/LexemeInterwikiLinks.js

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * This adds Wiktionary interwiki links in the sidebar on lexeme pages.
 * It links to pages corresponding to the first lemma and puts the lexeme
 * language's Wiktionary first, followed by languages in the user's Babel box.
 * 
 * To use it, add the following line to your common.js:
 * mw.loader.load("/w/index.php?title=User:Nikki/LexemeInterwikiLinks.js&action=raw&ctype=text/javascript");
 * 
 * @license CC0-1.0
*/

(function () {
	if (mw.config.get("skin") === "minerva") {
		// Broken in Minerva, T354123
		return;
	}

	if (mw.config.get("wgPageContentModel") !== "wikibase-lexeme") {
		// Not a lexeme
		return;
	}

	var babel = mw.config.get("wgULSBabelLanguages") || [];
	var lemma_langs = [];
	var uilang = mw.config.get("wgUserLanguage");

	function addPortlet(portlet_id, heading) {
		const portlet = mw.util.addPortlet(portlet_id, heading, "#p-tb");
		if (portlet) {
			portlet.parentNode.appendChild(portlet);
		}
		mw.util.showPortlet(portlet_id);
	}

	function sort_languages(a, b) {
		// Put the lexeme languages first
		if (lemma_langs.includes(a.lang)) {
			return -1;
		} else if (lemma_langs.includes(b.lang)) {
			return 1;
		}

		// Followed by the interface language
		if (a.lang === uilang) {
			return -1;
		} else if (b.lang === uilang) {
			return 1;
		}

		// Followed by languages in the user's Babel box
		if (babel.includes(a.lang)) {
			return -1;
		} else if (babel.includes(b.lang)) {
			return 1;
		}

		// Then sort alphabetically by language name
		return a.langname.localeCompare(b.langname);
	}

	function loaded(e) {
		if (!e.language) {
			// Not a lexeme
			return;
		}

		// Used by sort_languages()
		lemma_langs = Object.keys(e.lemmas);

		// Get the first lemma to use for the interwiki links
		// TODO: Find a way to use all lemmas?
		var lang = lemma_langs[0];
		var lemma = e.lemmas[lang].value;

		// The API query only includes pages on other domains.
		// To avoid having to do a second query to find out whether
		// the page exists on the API's domain, we can instead take
		// advantage of aa.wiktionary.org being a closed wiki with no pages.
		var remoteapi = new mw.ForeignApi("https://aa.wiktionary.org/w/api.php");
		remoteapi.get({
			"action": "parse",
			"prop": "langlinks",
			"text": "",
			"title": lemma,
			"uselang": uilang,
		}).done(function (data) {
			if (data.parse.langlinks.length === 0) {
				// No Wiktionary pages found
				return;
			}

			// Create portlet
			var portlet_id = "lexeme-interwiki";
			var heading = mw.msg("Wikibase-sitelinks-wiktionary");
			addPortlet(portlet_id, heading);

			// Add the Wiktionary links to the portlet
			$.each(data.parse.langlinks.sort(sort_languages), function (i, v) {
				mw.util.addPortletLink(portlet_id, v.url, v.langname);
			});
		});
	}

	var api = new mw.Api();
	api.loadMessages(["Wikibase-sitelinks-wiktionary"]).done(function () {
		mw.hook("wikibase.entityPage.entityLoaded").add(loaded);
	});

})();