User:TomT0m/LexToWiktionary.js
Jump to navigation
Jump to search
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.
/*jshint esversion: 8 */
mw.loader.using(["oojs-ui.styles.icons-editing-advanced"],
function() {
"use strict";
// only activate on lexeme namespace
let namespace = mw.config.get("wgNamespaceNumber");
if (namespace != mw.config.get("wgNamespaceIds").lexeme){
return;
}
$( `<style>
dl.wiktionaries_links dd {
display: inline;
margin: 0.3em;
padding : .3em ;
}
dl.wiktionaries_links dd:hover {
/*
same as rule : on vector style
.uls-language-block > ul > li:hover
*/
background-color: #eaeff7;
}
dl.wiktionaries_links dt:before{
display: block;
content: '';
}
dl.wiktionaries_links dd.iw_1
{
margin-left: 2em;
}
dl.wiktionaries_links dt{
/*display: inline-block;*/
min-width: 100px;
padding-left : .5em ;
}
.wikt-iw-container{
background-color: #fcfcfc;
}
dl.wiktionaries_links dd a {
cursor: pointer;
text-decoration: none;
color: #36c;
font-size: 1em;
/*display: inline-block;
width: 100%;*/
overflow-x: hidden;
padding: 8px;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
}
</style>`).appendTo( "head" );
function add_wiktionaries_without_duplicates(wiktionaries, adds){
return wiktionaries.concat(
adds.filter(wikt => ! wiktionaries.includes(wikt))
);
}
function select_wiktionaries_with_langs(wiktionaries, langCodes){
return wiktionaries.filter(
wikt_id => langCodes.includes(site_details[wikt_id].languageCode)
);
}
function choose_preferred_wiktionaries(wiktionaries){
// listing the wiktionaries
// corresponding to the babel boxes of the user
let userLang = mw.config.get("wgUserLanguage");
let babel_languages = mw.config.get("wgULSBabelLanguages");
let userlang_wiktionaries = select_wiktionaries_with_langs(
wiktionaries, [userLang]
);
let babel_dicts = select_wiktionaries_with_langs(
wiktionaries,
babel_languages
);
return add_wiktionaries_without_duplicates(userlang_wiktionaries, babel_dicts);
}
// returns a promise that takes a wiki and a page name and returns
// a list of wikilinks to the relevant pagenames
function pagename_to_languagelinks(pagenames, wiki_details){
var api = new mw.ForeignApi( wiki_details.apiUrl );
// using the "query" api call to get informations on page from titles
return api.get( {
action: 'query',
titles: pagenames,
} ).then(pages_candidates_answer => {
let pages_info = pages_candidates_answer.query.pages;
// on the answer, the non existing titles recieve a « missing » attribute
// keeping only those who don’t have
let pages = Object.keys(pages_info)
.filter(k => !( "missing" in pages_info[k]))
.map(k => pages_info[k].title);
let uls_langs = mw.config.get("wgULSLanguages");
// constructing the HTML link from all the informations
// about the site
return {
wiki : wiki_details,
links : pages.map(
pagename =>
$("<a />", {
href : wiki_details.pageUrl.replace("$1", pagename),
name : wiki_details.shortName,
append : pagename,
dir : $.uls.data.getDir(wiki_details.languageCode),
title : uls_langs[wiki_details.languageCode]
}
)
)};
});
}
// wrapping function to map on a list on wiki and returns a list of promises
// that finds the relevant wikipages on each wiki from the pagenames
// returns a function that will take a detail wiki as parameter and will lauch
// the treatment with the pagenames as parameters
function launch_treatment_for_wiki(pagenames, treatment, progress){
return async (wiki_details) => {
try {
let res = await treatment(pagenames, wiki_details);
progress();
return res;
} catch(error){
progress();
mw.log("error for wiki" + wiki_details.name, error.toString());
}
};
}
// UI : function that installs the language link button.
function install_iw_button(content, icon){
icon = icon ?? "language"; // jshint ignore:line
let align = "center";
if (mw.config.get("skin")=="minerva"){
align = "backwards";
}
let iw_popup =
new OO.ui.PopupButtonWidget( {
$overlay: true,
label: 'Wiktionary',
indicator: 'down',
icon : icon,
infusable:true,
popup: {
$content: $("<div>",{class:["gadget-wikt-iw-popup"]}).append(content),
padded: false,
align: align,
width: "50em",
},
class:["mw-portlet-lang"],
id :"gadget-wikt-iw-button"
} );
// $("#p-views > .vector-menu-content > .vector-menu-content-list")
// .prepend($("<li>").append(iw_popup.$element));
// html(iw_popup.$element);
$(".gadget-wikt-iw-container").html(iw_popup.$element);
// returns a function that can update the button content
return (content, icon) => {
iw_popup.setIcon(icon);
$(".gadget-wikt-iw-popup").html(content);
};
}
///////////////////////////////////////////
// installation of the gadget localisation depending on the skin
///////////////////////////////////////////
// installing the gadget view
function install_gadget_element(){
let vector2022_place = $("#p-views > .vector-menu-content > .vector-menu-content-list");
if (vector2022_place.length > 0) {
vector2022_place.prepend($("<li>",{class:"gadget-wikt-iw-container"}));
return true;
}
let minerva_neue = $("#p-tb");
if (minerva_neue.length == 1){
$("<li>)").addClass("gadget-wikt-iw-container")
.appendTo(minerva_neue);
return true;
}
return false;
}
// gadget initialisation
if (! install_gadget_element()){
console.log("Lexeme wiktionary language links : could not install for this skin ");
return;
}
let set_iw_button_content = install_iw_button(new OO.ui.ProgressBarWidget( {
progress: false
} ).$element);
let lexeme_id = mw.config.get("wbEntityId");
// getting the wiktionaries project infos
let site_details = mw.config.get("wbSiteDetails");
let wiktionaries = Object.keys(site_details)
.filter(
projectkey => (site_details[projectkey].group=="wiktionary")
);
// TODO : check if variants of languages works
let default_wiktionaries = choose_preferred_wiktionaries(wiktionaries);
let api = new mw.Api();
// real work :
// getting the lemma(s) of the lexeme and their langcodes
api.get({action:"wbgetentities", ids:lexeme_id})
.then(async (result) => {
const entity = result.entities;
const lemset = entity[lexeme_id].lemmas;
// computing the lemmas strings
let lemmas = Object.keys(lemset)
.map(lang => lemset[lang].value);
// listing the wiktionaries with the same language of the lexeme
let lemmas_langs = Object.keys(lemset);
let lexeme_wikts = select_wiktionaries_with_langs(wiktionaries, lemmas_langs);
// concatenating the lemmas lang and the user lang, removing duplicates
// first the lemmas lang
let preferred_wikts = add_wiktionaries_without_duplicates(lexeme_wikts, default_wiktionaries);
// queries : for all wiktionaries,
// searching titles that exists on the wiki, and generating the list of interwikis
// (call to all apis, in parralel)
async function query_wiktionaries_for_pages (wikts, lemmas, progress){
progress = progress ?? (() => {}) ; /* jshint ignore:line */
let wiki_pages_results = await Promise.all(
wikts
.map(wikt_id => site_details[wikt_id])
.map(launch_treatment_for_wiki(lemmas, pagename_to_languagelinks, progress))
);
console.log(wiki_pages_results);
return wiki_pages_results.filter(wiki => wiki && wiki.links.length>0);
}
function add_wiki_pages_to_list(list, links_of_wiki){
list.append(
links_of_wiki
.map(
wiki =>
[$("<dt>").append(wiki.wiki.shortName + " : ")].concat(
wiki.links.map((a, idx) => $("<dd>",{class: "iw_" + (idx+1)}).append(a))
)
).flat(1)
);
}
var links_of_wiki = await query_wiktionaries_for_pages(preferred_wikts, lemmas);
let list = $('<dl>',{class:["wiktionaries_links"]});
// adding a link to expand the list with all wiktionaries
let other = $("<a>",{text:"[other wiktionaries …]"}).click(
async () => {
let rest_of_wikis = add_wiktionaries_without_duplicates(wiktionaries, preferred_wikts);
var progressBar = new OO.ui.ProgressBarWidget( {
progress: 0
} );
other = other.replaceWith(progressBar.$element);
try {
var nb_done = 0;
let progress = () => {
nb_done += 1 ;
progressBar.setProgress(nb_done/rest_of_wikis.length * 100);
};
let links = await query_wiktionaries_for_pages(rest_of_wikis, lemmas, progress);
add_wiki_pages_to_list(list, links);
} catch(error){
other.replaceWith("Error !");
}
}
);
if(links_of_wiki.length == 0){
$(".gadget-wikt-iw-container").html("Wikt:nothing");
return;
}
// generating the final language links html links
add_wiki_pages_to_list(list, links_of_wiki);
// installing the language links button
set_iw_button_content($("<div>",{class:"wikt-iw-container"}).append(other).append(list),"language");
}).catch(error =>{
set_iw_button_content(new OO.ui.MessageWidget( {
type: 'error',
label: "could not load datas : " + error.toString()
} ).$element, "error");
console.log(error);
// $(".gadget-wikt-iw-container").html("Wikt:error !");
});
});