Utilisateur:Automatik/translation editor diff original.js
Remarque: après avoir sauvegardé, vous devez vider le cache de votre navigateur pour que les changements prennent effet. Mozilla, cliquez sur Actualiser (ou ctrl-r). Internet Explorer / Opera: ctrl-f5. Safari: cmd-r. Konqueror ctrl-r.
/*
* Mix des versions française et suédoise
* du gadget d'ajout de traductions
* commentant les différences entre les deux
*
* Les différences avec la version suédoise sont commentées en français
* et précédées de mon pseudo (Automatik)
*
* Le script dispose en plus d'une fonction de débug
* (affiche_wikitexte, définie juste ci-dessous)
*/
mw.loader.load('//sv.wiktionary.org/w/index.php?title=MediaWiki:Gadget-translation_editor.css&action=raw&ctype=text/css', 'text/css');
// Automatik : fonction de test pour afficher le wikitexte
// dans la fenêtre sans avoir à enregistrer
function affiche_wikitexte(wikitexte) {
wikitexte = wikitexte.replace(/</g, '<').replace(/>/g, '>').replace(/\n/g, '<br />');
$('<div>' + wikitexte + '</div>').insertBefore('body').css({
position: 'fixed',
left: '50%', top: '50%',
width: '500px', height: '300px',
marginLeft: '-250px', marginTop: '-150px',
border: '2px black solid',
backgroundColor: 'lightBlue',
zIndex: '500',
overflow: 'auto'
}).click(function() {$(this).detach();});
}
// exemple d'utilisation : affiche_wikitexte(wikicode) où wikicode est une variable
// contenant le wikicode à un moment donné du script (cf. plus bas dans le script)
/* Fichier [[MediaWiki:Gadget-silent fail storage.js]] */
// Local storage wrapper: the same as local storage, but fails silently if it
// is not supported.
window.silentFailStorage = (function () {
try {
// Will throw if localStorage isn't supported or if it's disabled
var l = window.localStorage,
val = l.getItem('a');
l.setItem('a', 'b');
if (l.getItem('a') === 'b') {
// it works
if (val !== null)
l.setItem('a', val);
else
l.removeItem('a');
return l;
}
} catch (e) {
}
function noop() {}
function rnull() { return null; }
return {
getItem: rnull,
setItem: noop,
removeItem: noop,
clear: noop,
key: rnull,
length: 0
};
})();
/* Fichier [[MediaWiki:Gadget-editor.js]] */
// This editor is inspired by Conrad.Irwin's editor.js.
// https://en.wiktionary.org/wiki/User:Conrad.Irwin/editor.js
// Singleton editor
window.editor = (function () {
/* global $, mw, wgPageName, wgScript, wgArticleId, wgRevisionId, wgCurRevisionId */
if (wgRevisionId !== wgCurRevisionId) {
return {};
}
// private variables and functions
var ed = { enabled: true },
api,
elem,
history,
// Points at the action that has been carried out
cursor;
function update_disabled() {
elem.find('.ed-undo').prop('disabled', cursor === 0);
elem.find('.ed-redo').prop('disabled', cursor === history.length - 1);
elem.find('.ed-save').prop('disabled', history[cursor].save !== 'yes');
}
function show() {
elem.show();
if (elem.hasClass('ed-highlight')) {
setTimeout(function () {
elem.removeClass('ed-highlight');
}, 500);
}
}
// public methods
ed.edit = edit;
function edit(rev) {
init();
history.length = cursor + 1;
if (!rev.save) {
rev.save = 'yes';
} else if (rev.save === 'ifprev') {
rev.save = history[cursor].save;
}
history.push(rev);
redo();
show();
}
ed.undo = undo;
function undo() {
history[cursor].undo();
cursor--;
update_disabled();
}
ed.undo_all = undo_all;
function undo_all() {
while (cursor) {
undo();
}
elem.hide();
}
ed.redo = redo;
function redo() {
history[cursor + 1].redo();
cursor++;
update_disabled();
}
ed.save = save;
function save() {
var wikitext = history[cursor].wikitext;
// Allow callbacks to make last-minute modifications before saving
for (var i = cursor; i; i--) {
if (history[i].onsave) {
wikitext = history[i].onsave(wikitext);
}
}
var log = $('<div>', {'class': 'ed-save'})
.append(
$('<small>', {text: summary()}),
' ',
$('<b>', {text: 'Sauvegarde en cours...'})
).appendTo(elem.find('.ed-inner'));
api.post({
action: 'edit',
title: wgPageName,
text: wikitext,
summary: summary(true),
notminor: '',
token: mw.user.tokens.get('csrfToken')
}).done(function (data) {
if (!data.edit || data.edit.result !== 'Success') {
log.addClass('error').find('b').text('Impossible d\'enregistrer');
return;
}
$('.ed-added').removeClass('ed-added');
history.length = 1;
cursor = 0;
log.find('b').text('Enregistré');
log.append(
' ',
$('<a>', {
text: 'Voir les changements',
href: wgScript +
'?title=' + encodeURIComponent(mw.config.get('wgPageName')) +
'&diff=' + data.edit.newrevid +
'&oldid=' + data.edit.oldrevid
})
);
history[0].wikitext = wikitext;
update_disabled();
}).fail(function (error) {
log.find('b').addClass('error').text('Sauvegarde impossible');
return;
});
}
ed.wikitext = wikitext;
function wikitext() {
return init() ||
new $.Deferred()
.resolve(history[cursor].wikitext)
.promise();
}
ed.summary = summary;
function summary(add_assisted) {
var parts = {};
for (var i = 1; i <= cursor; i++) {
var h = history[i];
if (!h.summary) {
continue;
}
if (h.summary_type) {
parts[h.summary_type] = h.summary;
} else if (!parts._) {
parts._ = h.summary;
} else {
parts._ += '; ' + h.summary;
}
}
return $.map(parts, function (x) { return x; }).join('; ') +
(add_assisted ? ' (assisté)' : '');
}
ed.init = init;
function init() {
if (elem) {
return;
}
history = [{
redo: null,
undo: null,
wikitext: null,
save: 'no'
}];
cursor = 0;
elem = $('<div>', { 'class': 'ed-box ed-highlight' })
.append(
'<a class="ed-close" href="#">×</a>' +
'<div class="ed-inner">' +
'<button class="ed-save" accesskey="s">Enregistrer les modifications</button><br>' +
'<button class="ed-undo">Annuler</button>' +
'<button class="ed-redo" disabled>Rétablir</button>' +
'</div>');
elem.find('.ed-close').click(function (e) { undo_all(); e.preventDefault(); });
elem.find('.ed-save').click(save);
elem.find('.ed-undo').click(undo);
elem.find('.ed-redo').click(redo);
elem.appendTo('body');
api = new mw.Api();
return api.get({
action: 'query',
prop: 'revisions',
titles: wgPageName,
rvprop: 'content',
}).then(function (data) {
var wikitext = data.query.pages[wgArticleId].revisions[0]['*'];
// Some scripts are strict, so remove trailing whitespace on non-empty lines
wikitext = wikitext.replace(/(\S)[ \t]+(\n|$)/g, '$1$2');
history[0].wikitext = wikitext;
return wikitext;
});
}
return ed;
})();
/* Fichier [[MediaWiki:Gadget-translation editor.js]] */
// This script enables adding translations without handling wikitext.
//
// It is very much inspired by User:Conrad.Irwin/editor.js. The reason
// I created this script was because editor.js was difficult to modify
// for the needs of sv-wikt. This script is, currently, no better, with
// sv-wikt's idiosyncrasies and Swedish littered all-over. The goal is,
// however, to move all of that to a configuration section.
//
// Main differences:
// * This uses jQuery, which greatly simplifies a lot of DOM stuff.
// * This handles fewer special cases and is therefore smaller.
// * This uses mw.Api (or $.ajax where mw.Api isn't sufficient).
// * This uses promises, editor.js uses callbacks.
//
// TODO:
// * Move out sv-wikt-specific stuff
// * Structure the code better
// * Handle special cases:
// - Reference to another page's translations
// - Parameter halv=
// - Translations that need to be checked
// - Warn on capital letters (except for German) and comma, unless the
// title contains one
//
//
// - Skalman
//
// P.S.
// Please contact me if you have questions!
// https://sv.wiktionary.org/wiki/Anv%C3%A4ndardiskussion:Skalman
/* global $, mw, editor, silentFailStorage, addGreenLinks, wgPageName */
( function( mw, $ ) { // Closure (fermée à la toute fin du script)
'use strict';
var
// Tableau de correspondance langue <-> code langue
// que l'on va charger à la prise de focus sur un formulaire
tab_langues,
// Id récupéré par la fonction add_heading_updater() pour
// typer correctement les résumés d'édition
heading_id_counter = 0;
// Automatik : L'élément table des autres wiktionnaires est l'élément div sur fr.wikt
if (editor.enabled) {
$('div.translations')
.filter(function ( index ) { // Automatik : on ne sélectionne pas les boites de traductions à trier
return $(this).parent().parent().parent().prev().prop( 'nodeName' ).toLowerCase() != 'h5' &&
!/^(?:Traductions )?à (?:trier|classer)/i.test($(this).parent().prev().children().first().text());
})
.each(function (i) {
add_translation_form(this, i);
add_heading_updater(this);
});
}
function get_translation_table_index(table) {
return $.inArray(table, $('div.translations'));
}
function get_error_html(message) {
return '<img src="//upload.wikimedia.org/wikipedia/commons/4/4e/MW-Icon-AlertMark.png"> ' + message;
}
function add_heading_updater(table) {
var id = heading_id_counter++;
var self = $(table).parent('.NavContent').prev('.NavHead');
var edit_head = $('<a>', {
href: '#',
text: '±',
'class': 'ed-edit-head',
title: 'Changer la description'
}).prependTo(self);
function remove_gloss_nodes() {
var nodes = [];
$.each(self[0].childNodes, function (i, node) {
if (node.className !== 'ed-edit-head' && node.className !== 'NavToggle') {
nodes.push(node);
}
});
$(nodes).detach();
return nodes;
}
var gloss_nodes;
edit_head.click(function (e) {
e.preventDefault();
if (self.find('form').length) {
self.find('form').remove();
self.append(gloss_nodes);
return;
}
edit_head.text('Chargement...');
editor.wikitext()
.then(function (wikitext) {
edit_head.text('±');
gloss_nodes = remove_gloss_nodes();
var prev_gloss_nodes = gloss_nodes;
var gloss = translation.get_gloss(wikitext, get_translation_table_index(table));
var form = $('<form>', { html:
'<label>Définition: <input name="gloss"></label>' +
'<button type="submit">Prévisualiser</button> ' +
'<span class="ed-loading"">Chargement...</span>' +
'<span class="ed-errors""></span>'
});
function error() {
form.find('.ed-errors')
.html(get_error_html('La description n\'a pas un format correct : elle contient du wikitexte ([]{}#|)' +
' (alors que {{trad-début}} est absent)'));
}
self.append(form);
form.find('input')
.val(gloss.standard ? gloss.text : gloss.trans_top)
.focus();
form.click(function (e) {
e.stopPropagation();
}).submit(function (e) {
e.preventDefault();
var gloss_wikitext = this.gloss.value;
if (!translation.is_trans_top(gloss_wikitext) && translation.contains_wikitext(gloss_wikitext)) {
error();
return;
}
form.find('.ed-loading').show();
$.when(
parse_wikitext(translation.make_trans_top(gloss_wikitext)),
// get wikitext again in case it has changed since last time
editor.wikitext()
).done(function (gloss_html, wikitext) {
gloss_html = $(gloss_html);
var prev_class = self.parent('.NavFrame').attr('class');
var new_class = gloss_html.filter('.NavFrame').attr('class');
gloss_html = gloss_html.find('.NavHead').contents();
form.remove();
wikitext = translation.set_gloss(
wikitext,
get_translation_table_index(table),
gloss_wikitext
);
// Automatik : Utile pour afficher le wikitexte sans avoir à l'enregistrer
// affiche_wikitexte(wikitext);
editor.edit({
wikitext: wikitext,
summary: 'traductions : "' + gloss_wikitext + '"',
summary_type: 'gloss' + id,
redo: function () {
remove_gloss_nodes();
$('<span>', {
'class': 'ed-added',
html: gloss_html
}).appendTo(self) ;
if (prev_class !== new_class) {
self.parent('.NavFrame').attr('class', new_class);
}
},
undo: function () {
remove_gloss_nodes();
self.append(prev_gloss_nodes);
if (prev_class !== new_class) {
self.parent('.NavFrame').attr('class', prev_class);
}
}
});
});
});
});
});
}
/* Automatik : balancement inadapté à fr.wikt
function add_balancer(self, i) {
var row = self.find('tr:first-child');
if (row.children().length === 1) {
row.append('<td>', row.children().first().clone().text(''));
}
var cell = row.children().eq(1);
if (cell.find('button').length) {
return;
}
cell.css('vertical-align', 'middle')
.append(
$('<button>', { text: '←', click: balance, value: -1 }),
$('<br>'),
$('<button>', { text: '→', click: balance, value: 1 })
);
var first_list = row.children().first().children('ul');
var last_list = row.children().last().children('ul');
if (!first_list.length) {
first_list = $('<ul>').appendTo(row.children().first());
}
if (!last_list.length) {
last_list = $('<ul>').appendTo(row.children().last());
}
function move(direction) {
if (direction === 1) {
first_list.children().last().prependTo(last_list);
} else {
last_list.children().first().appendTo(first_list);
}
}
function balance() {
var direction = +this.value;
editor.wikitext()
.done(function (wikitext) {
var balanced_wikitext = translation.balance(wikitext, i, direction);
if (balanced_wikitext === wikitext) {
throw new Error('Ingen översättning att flytta');
}
editor.edit({
wikitext: balanced_wikitext,
summary: 'balansera',
summary_type: 'balance',
redo: function () {
move(direction);
},
undo: function () {
move(-direction);
}
});
});
}
}
*/
function add_translation_form(table) {
var self = $(table);
// Automatik : aucune traduction dans la boite, on rajoute le 'ul' pour pouvoir y attacher le formulaire
if ( self.children().length === 0 || self.children().prop('nodeName').toLowerCase() !== 'ul' ) {
self.append( $( '<ul></ul>' ) );
}
var ul = self.children().filter(function() {
return $(this).prop('nodeName').toLowerCase() === 'ul';
}).first();
var lang_meta = {
'': '', // Automatik : par défaut, ni genre ni nombre à cocher
allemand: 'm f n p',
chinois: 'trans tradi',
'coréen': 'trans tradi',
danois: 'c n p',
espagnol: 'm f p',
'féroïen': 'm f n',
islandais: 'm f n p',
italien: 'm f p',
japonais: 'trans',
latin: 'm f n p',
letton: 'm f p',
'néerlandais': 'm f n p',
'norvégien': 'm f n p',
'norvégien (nynorsk)': 'm f n p',
polonais: 'm f n p',
portugais: 'm f p',
'suédois': 'c n',
};
var options = $.map({
gender: { // Automatik : sur le Wiktionnaire on n'a qu'un paramètre pour le genre, et pas d'autre pour le nombre
m: 'masc.',
f: 'fém.',
mf: 'masc. & fém.',
n: 'neutre',
c: 'commun',
s: 'singulier',
p: 'pluriel'
}/*, Automatik : Pas de paramètre pour le nombre dans les modèles de traduction
number: {
s: 'singulier',
d: 'duel',
p: 'pluriel'
}*/
}, function (items, name) {
items = $.map(items, function (text, value) {
return '<label class="ed-' + value + '">' +
'<input type="radio" name="' + name + '" value="' + value + '">' +
text +
'</label>';
});
return '<p class="ed-options ed-' + name + '">' + items.join(' ') + '</p>';
}).join('') +
'<p class="ed-options"><label class="ed-trans">Translittération : <input name="trans"></label></p>' +
'<p class="ed-options"><label class="ed-tradi">Écriture traditionnelle : <input name="tradi"></label></p>'/* +
'<p class="ed-options"><label class="ed-note">Note : <input name="note"></label></p>'*/; // Automatik : paramètre note spécifique au modèle de trad. suédois
var form = $($.parseHTML('<form>' + // '<form><ul><li>' + Automatik : déjà un li avant 'form'
'<p><label><span class="txt-label">Ajouter une traduction </span>' +
'<input class="ed-lang-name" name="lang_name" size="3" title="Nom de langue (anglais,...)"></label> : ' +
'<input class="ed-word" name="word" size="20" title="traduction"> ' +
'<button type="submit">Prévisualiser</button> ' +
'<a href="#" class="ed-more">Plus</a></p>' +
options +
'<div class="ed-errors"></div>' +
'</form>')); // '</li></ul></form>')); Automatik : déjà un li avant 'form'
// Make radio buttons deselectable
form.find(':radio').click(function last_click(e) {
if (last_click[this.name] === this) {
last_click[this.name] = null;
this.checked = false;
} else {
last_click[this.name] = this;
}
});
var show_all_opts = false;
form.find('.ed-lang-name')
// Automatik : remplacement éventuel code langue -> nom langue
.blur(remplace_code_langue)
.blur(update_options_visibility)
// If the item exists, the value will be used as the value,
// otherwise it's 'null', which empties (the already empty)
// text field.
.val(silentFailStorage.getItem('trans-lang'));
form.find('.ed-more').click(function (e) {
e.preventDefault();
show_all_opts = !show_all_opts;
$(this).text(show_all_opts ? 'Moins' : 'Plus');
update_options_visibility();
});
update_options_visibility();
function update_options_visibility() {
var elems = form.find('.ed-options label');
if (show_all_opts) {
elems.show();
// Automatik : On affiche le champ pour l'écriture traditionnelle
// uniquement en chinois et en coréen
var lang_name = form.find('.ed-lang-name').val();
if ($.inArray(lang_name, ['chinois', 'coréen']) === -1) {
form.find('.ed-tradi').hide();
}
} else {
var opts = lang_meta[form[0].lang_name.value] || lang_meta[''];
elems
.hide()
.filter('.ed-' + opts.replace(/ /g, ', .ed-')).show();
}
}
// Automatik : fonction pour déterminer si une chaine
// correspond à un nom de langue dans le tableau
function is_lang_name(str) {
if (typeof tab_langues === 'undefined') {
return undefined;
}
for (var code in tab_langues) {
if (tab_langues[code] === str) {
return true;
}
}
return false;
}
// Automatik : fonction de remplacement code langue -> nom de langue
// lancée à la perte de focus du champ du code langue
function remplace_code_langue() {
var elem = form.find('.ed-lang-name');
var val = elem.val();
if (val === '') {
elem.attr('title', 'Nom de langue (ex : anglais)');
return;
}
if (is_lang_name(val)) {
return;
}
if (tab_langues.hasOwnProperty(val)) {
elem.val(tab_langues[val]);
return;
}
elem.attr('title', 'Nom de langue (ex : anglais)');
}
$('<li>').append(form)
.appendTo(ul);
// Automatik : élargissement du champ pour entrer le nom de la langue
self.find('.ed-lang-name').focus(function() {
self.find('.txt-label').css('display', 'none');
$(this).prop('size', 10);
$(this).select();
});
self.find('input').focus(function () {
editor.init();
// Automatik : on charge le tableau de correspondance langues <-> codes langue
// si ça n'est pas déjà fait
if (typeof tab_langues === 'undefined') {
var api = new mw.Api();
return api.get({
action: 'query',
format: 'json',
titles: 'Utilisateur:Automatik/langues.json',
prop: 'revisions',
rvprop: 'content'
}).then(function (data) {
// Afin d'obtenir la première page du résultat,
// boucle arrêtée dès le premier tour
for (var pageid in data.query.pages) break;
tab_langues = JSON.parse(data.query.pages[pageid].revisions[0]['*']);
// On crée le tableau des noms de langues pour l'autocomplétion
var tab_lang_names = [];
for (var code in tab_langues) {
tab_lang_names.push(tab_langues[code]);
}
// Autocomplétion du nom de langue
mw.loader.using('jquery.ui', function() {
$('.ed-lang-name').autocomplete({
source: function( request, response ) {
var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( request.term ), "i" );
response( $.grep( tab_lang_names, function( item ){
return matcher.test( item );
}) );
},
minLength: 2
});
});
});
}
});
form.submit(function (e) {
e.preventDefault();
// Automatik : On "trime" les valeurs afin d'enlever les éventuels espaces superflus autour de la chaine (copiée-collée depuis un texte...)
var lang_name = $.trim(this.lang_name.value);
var word = $.trim(this.word.value);
var gender = form.find('.ed-gender input:checked').prop('checked', false).val();
var number = form.find('.ed-number input:checked').prop('checked', false).val();
var trans = $.trim(this.trans.value);
var tradi = $.trim(this.tradi.value);
// var note = this.note.value; // Automatik : pas adapté à fr.wikt à priori
silentFailStorage.setItem('trans-lang', lang_name);
if (!lang_name) {
show_error(new NoInputError('lang-name'));
return;
} else if (!word) {
show_error(new NoInputError('word'));
return;
} else if (lang_name === 'français' || lang_name === 'fr') {
show_error(new BadLangNameError());
return;
} else if (translation.re_wikitext.test(word)) {
show_error(new BadFormatError());
return;
}
var word_options = {
lang_name: lang_name,
lang_code: null,
word: word,
exists: null,
gender: gender,
// number: number,
trans: trans,
tradi: tradi // Automatik : ajouté
// note: note
};
function show_error(e) {
form.find('.ed-error').removeClass('ed-error');
if (!e) {
form.find('.ed-errors').empty();
return;
}
if (e instanceof NoLangTplError) {
form.find('.ed-lang-name').addClass('ed-error').focus();
e = 'La langue "' + e.lang_name + '" n\'est pas définie.';
} else if (e instanceof NoInputError) {
form.find('.ed-' + e.input).addClass('ed-error').focus();
if (e.input === 'lang-name') {
e = 'Entrez le nom de langue (anglais, suédois,...)';
} else if (e.input === 'word') {
e = 'Entrez la traduction';
}
} else if (e instanceof BadLangNameError) {
form.find('.ed-lang-name').addClass('ed-error').focus();
e = 'Il n\'est pas possible d\'ajouter une traduction en français. ' +
'À la place, veuillez utiliser la section « Synonymes » ou ' +
'« Variantes dialectales ».';
} else if (e instanceof BadFormatError) {
form.find('.ed-word').addClass('ed-error').focus();
e = 'La traduction n\'est pas dans un format correct : ' +
'elle contient du wikitexte ([]{}|=)';
} else if (e instanceof HttpError) {
e = 'Vous ne pouvez pas charger la traduction. Êtes-vous en ligne ?';
}
form.find('.ed-errors').html(get_error_html(e));
}
var lang_code;
// Automatik : on convertit le nom de langue en code
if (typeof tab_langues !== 'undefined') {
// Le tableau des langues contient-il le nom de langues
// donné ?
for (var code in tab_langues) {
if (tab_langues[code] === lang_name) {
lang_code = code;
break;
}
}
// Si le nom de langue donné n'est pas répertorié
// on regarde si ce n'est pas un code langue
if (lang_code === undefined) {
if (tab_langues[lang_name]) {
lang_code = lang_name;
lang_name = tab_langues[lang_code];
word_options.lang_name = lang_name;
} else {
show_error(new NoLangTplError(lang_name));
return;
}
}
} else {
throw new Error('Le tableau des langues n\'est pas défini.');
}
word_options.lang_code = lang_code;
$.when(
// word_html
page_exists(lang_code, word)
.then(function (page_exists) {
word_options.exists = page_exists;
return parse_wikitext(translation.get_formatted_word(word_options))
.then(function (html) {
return html;
});
}),
// wikitext
editor.wikitext()
).fail(function (error) {
if (error === 'http') {
// jQuery HTTP error
show_error(new HttpError());
} else {
show_error(error);
}
}).done(function (word_html, wikitext) {
show_error(false);
silentFailStorage.setItem('trans-lang', lang_name);
form[0].word.value = '';
form[0].trans.value = '';
form[0].tradi.value = '';
// form[0].note.value = ''; // Automatik : paramètre note inutilisé
// Automatik : on a déjà le nom de langue
// word_options.lang_name = lang_name;
var added_elem;
var index = get_translation_table_index(table);
wikitext = translation.add(wikitext, index, word_options);
// Automatik : pour afficher le wikitexte résultant sans enregistrer
// affiche_wikitexte(wikitext);
// add_balancer(self, index); // Automatik : pas besoin du balancement
editor.edit({
summary: '+' + lang_code + ' : [[' + word + ']]',
wikitext: wikitext,
redo: function () {
var translations = self.find('ul > li');
translation.add_to_list({
items: translations.slice(0, -1), // Automatik : le slice afin d'ignorer le formulaire dans la recherche des noms de langues
add_only_item: function () {
added_elem = $('<li>', { html: '<span class="trad-' + lang_code +
'">' + lang_name.charAt(0).toUpperCase() + lang_name.substr(1) + '</span> : ' + word_html });
self.find('ul').prepend(added_elem);
},
equal_or_before: function (item) {
var match = /^\s*(.{3,})/.exec($(item).children().first().text());
if (match) {
if (match[1] === 'Conventions internationales') return 'before'; // Automatik : conventions internationales en premier
if (match[1] === 'Traductions manquantes.') return false; // Automatik : on ignore les {{ébauche-trad}}
if (sortkey(match[1].toLowerCase()) === sortkey(lang_name.toLowerCase())) {
return 'equal';
} else if (sortkey(match[1].toLowerCase()) < sortkey(lang_name.toLowerCase())) {
return 'before';
}
}
return false;
},
add_to_item: function (item) {
added_elem = $('<span>', { html: ', ' + word_html})
.appendTo(item);
},
add_after: function (item) {
added_elem = $('<li>', { html: '<span class="trad-' + lang_code +
'">' + lang_name.charAt(0).toUpperCase() + lang_name.substr(1) + '</span> : ' + word_html })
.insertAfter(item);
},
add_before: function (item) {
added_elem = $('<li>', { html: '<span class="trad-' + lang_code +
'">' + lang_name.charAt(0).toUpperCase() + lang_name.substr(1) + '</span> : ' + word_html });
/*if ($(item).is('td')) {
// Special case: {{ö-mitt}}
self.find('tr:first-child > td:first-child > ul').append(added_elem);
} else {*/
added_elem.insertBefore(item);
//} Automatik : les commentaires des 5 lignes précédentes pceque nous ne risquons
// pas de tomber sur un 'td' durant le parcours d'une table de traductions
},
});
added_elem.addClass('ed-added');
if (window.CrTr_ChangerLiensRouges) window.CrTr_ChangerLiensRouges(); // Automatik : adapté à CreerTrad.js
},
undo: function () {
added_elem.remove();
}
});
});
});
}
function parse_wikitext(wikitext) {
return new mw.Api().get({
action: 'parse',
text: '<div>' + wikitext + '</div>',
title: wgPageName
}).then(function (data) {
var html = data.parse.text['*'];
// Get only the parts between <div> and </div>
html = html.substring(
html.indexOf('<div>') + '<div>'.length,
html.lastIndexOf('</div>')
);
return $.trim(html);
});
}
function page_exists(lang_code, page) {
// Automatik : gestion correcte des liens interwikis
// dont le code wikimédia est différent du code
// utilisé en interne sur le Wiktionnaire
var wm_liens = {
'cmn': 'zh',
'fra-nor': 'nrm',
'gsw': 'als',
'ko-Hani': 'ko',
'lzh': 'zh-classical',
'nan': 'zh-min-nan',
'nb': 'no',
'rup': 'roa-rup',
'yue': 'zh-yue'
};
if (wm_liens.hasOwnProperty(lang_code))
lang_code = wm_liens[lang_code];
var def = $.Deferred();
$.ajax({
url: '//' + lang_code + '.wiktionary.org/w/api.php?origin=' + location.protocol + '//' + location.host,
data: {
action: 'query',
titles: page,
format: 'json'
},
dataType: 'json'
}).fail(function () {
def.resolve('nowikt');
}).then(function (data) {
def.resolve(!data.query.pages[-1]);
});
return def.promise();
}
// Automatik : ajout pour le Wiktionnaire francophone,
// adapté de [[MediaWiki:Gadget-CommonWikt.js]], fonction CleDeTri
function sortkey(word) {
var key = word.toLowerCase();
key = key.replace( /[àáâãäå]/g, "a" );
key = key.replace( /[æ]/g, "ae" );
key = key.replace( /[çćċč]/g, "c" );
key = key.replace( /[ĉ]/g, "cx" );
key = key.replace( /[èéêë]/g, "e" );
key = key.replace( /[ĝ]/g, "gx" );
key = key.replace( /[ĥ]/g, "hx" );
key = key.replace( /[ìíîï]/g, "i" );
key = key.replace( /[ĵ]/g, "jx" );
key = key.replace( /[ñ]/g, "n" );
key = key.replace( /[òóôõö]/g, "o" );
key = key.replace( /[œ]/g, "oe" );
key = key.replace( /[òóôõö]/g, "o" );
key = key.replace( /[ŝ]/g, "sx" );
key = key.replace( /[ùúûü]/g, "u" );
key = key.replace( /[ŭ]/g, "ux" );
key = key.replace( /[ýÿ]/g, "y" );
key = key.replace( /['’)(]/g, "" );
key = key.replace( /[-\/]/g, " " );
return key;
}
var translation = {
re_wikitext: /[[\]{}#|=]/,
contains_wikitext: function (str) {
return translation.re_wikitext.test(str);
},
// Automatik : regex plus souple, afin de prendre
// en compte les modèles dans l'en-tête des boites
// de traduction
re_gloss: /\{\{trad-début(.*)\}\}/g,
// Automatik : idem
re_section: /(\{\{trad-début.*\}\})([\s\S]*?)(\{\{trad-fin\}\})/g,
is_trans_top: function (gloss) {
return gloss.replace(translation.re_gloss, '-') === '-';
},
make_trans_top: function (gloss) {
if (translation.is_trans_top(gloss)) {
return gloss;
} else {
return '{{trad-début|' + gloss + '}}';
}
},
get_gloss: function (wikitext, index) {
if (/\{\{trad-début\|.*?(?:<!--|-->)/.test(wikitext)) { // Automatik : restriction de la condition sur la présence de commentaire
mw.notify('Le wikitexte contient un commentaire "<!--". La page doit être modifiée manuellement.');
throw new Error('Le wikitexte contient un commentaire "<!--". La page doit être modifiée manuellement.');
}
translation.re_gloss.lastIndex = 0;
for (var i = 0; i <= index; i++) {
var match = translation.re_gloss.exec(wikitext);
if (i === index && match) {
var standard = /^(|\|[^|=]*)$/.test(match[1]);
return {
trans_top: match[0],
text: standard ? match[1].substr(1) : void 0,
standard: standard
};
}
}
throw new Error('Le ' + (index+1) + '-ème {{trad-début}} n\'a pas été trouvé dans le wikitexte.');
},
set_gloss: function (wikitext, index, gloss) {
index++;
var count = 0;
return wikitext.replace(translation.re_gloss, function (match, p1, p2) {
count++;
if (count !== index) {
return match;
}
return translation.make_trans_top(gloss);
});
},
get_formatted_word: function (opts) {
var tpl = [
opts.exists === 'nowikt' ? 'trad--' : (opts.exists === true ? 'trad+' : 'trad-'),
opts.lang_code,
opts.word
];
opts.gender && tpl.push(opts.gender);
// opts.number && tpl.push(opts.number);
opts.trans && tpl.push('tr=' + opts.trans);
opts.tradi && tpl.push('tradi=' + opts.tradi);
// opts.note && tpl.push('not=' + opts.note);
return '{{' + tpl.join('|') + '}}';
},
// Options:
// - items: Array of items
// - equal_or_before: Function that returns either 'equal', 'before' or false
// - add_to_item: Adds a word to an item
// - add_after: Adds the item after an item
// - add_before: Adds the item before an item
add_to_list: function (opts) {
var items = opts.items;
if (!items.length) {
items[0] = opts.add_only_item();
return items;
}
for (var i = items.length - 1; i >= 0; i--) {
var eq_or_bef = opts.equal_or_before(items[i]);
if (eq_or_bef === 'equal') {
items[i] = opts.add_to_item(items[i]);
return items;
} else if (eq_or_bef === 'before') {
items[i] = opts.add_after(items[i]);
return items;
}
}
items[0] = opts.add_before(items[0]);
return items;
},
add: function (wikitext, index, opts) {
if (wikitext.match(translation.re_section)[index].indexOf('<!--') !== -1) { // Automatik : restriction + faible sur la présence de commentaire
mw.notify('Le wikitexte contient un commentaire "<!--". La page doit être modifiée manuellement.');
throw new Error('Le wikitexte contient un commentaire "<!--". La page doit être modifiée manuellement.');
}
index++;
var count = 0;
return wikitext.replace(translation.re_section, function (match, p1, p2, p3) {
count++;
if (count !== index) {
return match;
}
p2 = $.trim(p2);
var formatted_word = translation.get_formatted_word(opts);
var lines = translation.add_to_list({
// split into lines
items: p2 ? p2.split('\n') : [],
add_only_item: function () {
return '* {{T|' + opts.lang_code + '}} : ' + formatted_word;
},
equal_or_before: function (line) {
var match = /^\*\s*\{\{T\|([^}|]+?)\}\}\s*[(:]/.exec(line); // Automatik : [(:] car on peut avoir un dialecte précisé entre parenthèses
if (match) {
var code_langue = match[1];
if (code_langue === 'conv') {
return 'before'; // Automatik : conventions internationales en premier
}
if (sortkey(tab_langues[code_langue]) === sortkey(opts.lang_name)) {
if (/^\*\s*\{\{T\|[^}|]+?\}\}\s*:\s*$/.exec(line)) {
mw.notify('Il n\'est pas possible d\'ajouter une traduction dans cette langue,' +
' car le format est inhabituel.');
throw new Error('Format incorrect : le wikicode des traductions dans cette langue ' +
'est inhabituel et la traduction ne peut donc pas être ajoutée par le gadget.');
}
return 'equal';
} else if (sortkey(tab_langues[code_langue]) < sortkey(opts.lang_name)) {
return 'before';
}
}
return false;
},
add_to_item: function (line) {
return line + ', ' + formatted_word;
},
add_before: function (line) {
return this.add_only_item() + '\n' + line;
},
add_after: function (line) {
return line + '\n' + this.add_only_item();
}
});
/*if (p2.indexOf('{{ö-mitt}}') === -1) {
lines.push('{{ö-mitt}}');
}*/
return p1 + '\n' + lines.join('\n') + '\n' + p3;
});
},
/* Automatik : on récupèrera les noms de langues
depuis le tableau des langues chargé au focus
d'un formulaire de traduction
get_language: function (lang_code) {
var known = {
en: 'engelska',
fi: 'finska',
};
if (lang_code in known) {
return $.Deferred().resolve(known[lang_code]).promise();
} else {
return new mw.Api().get({
action: 'expandtemplates',
text: '{{' + lang_code + '}}'
}).then(function (data) {
data = data.expandtemplates['*'];
if (data.substr(0, 3) === '[[:') {
return $.Deferred().reject(new NoLangTplError(lang_code)).promise();
}
return data;
});
}
},
*/
/* Automatik : balancement non utile sur fr.wikt
balance: function (wikitext, index, direction) {
if (wikitext.indexOf('<!--') !== -1) {
throw new Error('Wikitext innehåller "<!--". Ändra manuellt.');
}
index++;
var count = 0;
return wikitext.replace(translation.re_section, function (match, p1, p2, p3) {
count++;
if (count !== index) {
return match;
}
if (/(^|\n)(\*\*|\*:|:)/.test(p2)) {
throw new Error('Kan inte balansera pga. indragna rader');
}
p2 = $.trim(p2);
var lines = p2 ? p2.split('\n') : [];
for (var i = 0; i < lines.length; i++) {
if (lines[i] === '{{ö-mitt}}') {
if (!lines[i - direction]) {
// nowhere to move
return match;
}
lines[i] = lines[i - direction];
lines[i - direction] = '{{ö-mitt}}';
return p1 + '\n' + lines.join('\n') + '\n' + p3;
}
}
// couldn't find {{ö-mitt}}
return match;
});
}*/
};
function extend_error(name, p1_name) {
function E(p1) {
this.message = p1;
if (p1_name) this[p1_name] = p1;
}
E.prototype = new Error();
E.prototype.constructor = E;
E.prototype.name = name;
return E;
}
var NoLangTplError = extend_error('NoLangTplError', 'lang_name');
var NoInputError = extend_error('NoInputError', 'input');
var BadLangNameError = extend_error('BadLangNameError');
var BadFormatError = extend_error('BadFormatError');
var HttpError = extend_error('HttpError');
// Export some useful components
window.translation = translation;
window.parse_wikitext = parse_wikitext;
window.add_heading_updater = add_heading_updater;
window.add_translation_form = add_translation_form;
} ( mediaWiki, jQuery ) ); // Fin de la closure ouverte au tout début